##// END OF EJS Templates
Fixed random tag image
neko259 -
r1417:f79d6211 default
parent child Browse files
Show More
@@ -1,142 +1,142 b''
1 import hashlib
1 import hashlib
2 from django.template.loader import render_to_string
2 from django.template.loader import render_to_string
3 from django.db import models
3 from django.db import models
4 from django.db.models import Count
4 from django.db.models import Count
5 from django.core.urlresolvers import reverse
5 from django.core.urlresolvers import reverse
6
6
7 from boards.models.base import Viewable
7 from boards.models.base import Viewable
8 from boards.models.thread import STATUS_ACTIVE, STATUS_BUMPLIMIT, STATUS_ARCHIVE
8 from boards.models.thread import STATUS_ACTIVE, STATUS_BUMPLIMIT, STATUS_ARCHIVE
9 from boards.utils import cached_result
9 from boards.utils import cached_result
10 import boards
10 import boards
11
11
12 __author__ = 'neko259'
12 __author__ = 'neko259'
13
13
14
14
15 RELATED_TAGS_COUNT = 5
15 RELATED_TAGS_COUNT = 5
16
16
17
17
18 class TagManager(models.Manager):
18 class TagManager(models.Manager):
19
19
20 def get_not_empty_tags(self):
20 def get_not_empty_tags(self):
21 """
21 """
22 Gets tags that have non-archived threads.
22 Gets tags that have non-archived threads.
23 """
23 """
24
24
25 return self.annotate(num_threads=Count('thread_tags')).filter(num_threads__gt=0)\
25 return self.annotate(num_threads=Count('thread_tags')).filter(num_threads__gt=0)\
26 .order_by('-required', 'name')
26 .order_by('-required', 'name')
27
27
28 def get_tag_url_list(self, tags: list) -> str:
28 def get_tag_url_list(self, tags: list) -> str:
29 """
29 """
30 Gets a comma-separated list of tag links.
30 Gets a comma-separated list of tag links.
31 """
31 """
32
32
33 return ', '.join([tag.get_view() for tag in tags])
33 return ', '.join([tag.get_view() for tag in tags])
34
34
35
35
36 class Tag(models.Model, Viewable):
36 class Tag(models.Model, Viewable):
37 """
37 """
38 A tag is a text node assigned to the thread. The tag serves as a board
38 A tag is a text node assigned to the thread. The tag serves as a board
39 section. There can be multiple tags for each thread
39 section. There can be multiple tags for each thread
40 """
40 """
41
41
42 objects = TagManager()
42 objects = TagManager()
43
43
44 class Meta:
44 class Meta:
45 app_label = 'boards'
45 app_label = 'boards'
46 ordering = ('name',)
46 ordering = ('name',)
47
47
48 name = models.CharField(max_length=100, db_index=True, unique=True)
48 name = models.CharField(max_length=100, db_index=True, unique=True)
49 required = models.BooleanField(default=False, db_index=True)
49 required = models.BooleanField(default=False, db_index=True)
50 description = models.TextField(blank=True)
50 description = models.TextField(blank=True)
51
51
52 parent = models.ForeignKey('Tag', null=True, blank=True,
52 parent = models.ForeignKey('Tag', null=True, blank=True,
53 related_name='children')
53 related_name='children')
54
54
55 def __str__(self):
55 def __str__(self):
56 return self.name
56 return self.name
57
57
58 def is_empty(self) -> bool:
58 def is_empty(self) -> bool:
59 """
59 """
60 Checks if the tag has some threads.
60 Checks if the tag has some threads.
61 """
61 """
62
62
63 return self.get_thread_count() == 0
63 return self.get_thread_count() == 0
64
64
65 def get_thread_count(self, status=None) -> int:
65 def get_thread_count(self, status=None) -> int:
66 threads = self.get_threads()
66 threads = self.get_threads()
67 if status is not None:
67 if status is not None:
68 threads = threads.filter(status=status)
68 threads = threads.filter(status=status)
69 return threads.count()
69 return threads.count()
70
70
71 def get_active_thread_count(self) -> int:
71 def get_active_thread_count(self) -> int:
72 return self.get_thread_count(status=STATUS_ACTIVE)
72 return self.get_thread_count(status=STATUS_ACTIVE)
73
73
74 def get_bumplimit_thread_count(self) -> int:
74 def get_bumplimit_thread_count(self) -> int:
75 return self.get_thread_count(status=STATUS_BUMPLIMIT)
75 return self.get_thread_count(status=STATUS_BUMPLIMIT)
76
76
77 def get_archived_thread_count(self) -> int:
77 def get_archived_thread_count(self) -> int:
78 return self.get_thread_count(status=STATUS_ARCHIVE)
78 return self.get_thread_count(status=STATUS_ARCHIVE)
79
79
80 def get_absolute_url(self):
80 def get_absolute_url(self):
81 return reverse('tag', kwargs={'tag_name': self.name})
81 return reverse('tag', kwargs={'tag_name': self.name})
82
82
83 def get_threads(self):
83 def get_threads(self):
84 return self.thread_tags.order_by('-bump_time')
84 return self.thread_tags.order_by('-bump_time')
85
85
86 def is_required(self):
86 def is_required(self):
87 return self.required
87 return self.required
88
88
89 def get_view(self):
89 def get_view(self):
90 link = '<a class="tag" href="{}">{}</a>'.format(
90 link = '<a class="tag" href="{}">{}</a>'.format(
91 self.get_absolute_url(), self.name)
91 self.get_absolute_url(), self.name)
92 if self.is_required():
92 if self.is_required():
93 link = '<b>{}</b>'.format(link)
93 link = '<b>{}</b>'.format(link)
94 return link
94 return link
95
95
96 def get_search_view(self, *args, **kwargs):
96 def get_search_view(self, *args, **kwargs):
97 return render_to_string('boards/tag.html', {
97 return render_to_string('boards/tag.html', {
98 'tag': self,
98 'tag': self,
99 })
99 })
100
100
101 @cached_result()
101 @cached_result()
102 def get_post_count(self):
102 def get_post_count(self):
103 return self.get_threads().aggregate(num_posts=Count('multi_replies'))['num_posts']
103 return self.get_threads().aggregate(num_posts=Count('multi_replies'))['num_posts']
104
104
105 def get_description(self):
105 def get_description(self):
106 return self.description
106 return self.description
107
107
108 def get_random_image_post(self, status=False):
108 def get_random_image_post(self, status=[STATUS_ACTIVE, STATUS_BUMPLIMIT]):
109 posts = boards.models.Post.objects.annotate(images_count=Count(
109 posts = boards.models.Post.objects.annotate(images_count=Count(
110 'images')).filter(images_count__gt=0, threads__tags__in=[self])
110 'images')).filter(images_count__gt=0, threads__tags__in=[self])
111 if status is not None:
111 if status is not None:
112 posts = posts.filter(thread__status=status)
112 posts = posts.filter(thread__status__in=status)
113 return posts.order_by('?').first()
113 return posts.order_by('?').first()
114
114
115 def get_first_letter(self):
115 def get_first_letter(self):
116 return self.name and self.name[0] or ''
116 return self.name and self.name[0] or ''
117
117
118 def get_related_tags(self):
118 def get_related_tags(self):
119 return set(Tag.objects.filter(thread_tags__in=self.get_threads()).exclude(
119 return set(Tag.objects.filter(thread_tags__in=self.get_threads()).exclude(
120 id=self.id).order_by('?')[:RELATED_TAGS_COUNT])
120 id=self.id).order_by('?')[:RELATED_TAGS_COUNT])
121
121
122 @cached_result()
122 @cached_result()
123 def get_color(self):
123 def get_color(self):
124 """
124 """
125 Gets color hashed from the tag name.
125 Gets color hashed from the tag name.
126 """
126 """
127 return hashlib.md5(self.name.encode()).hexdigest()[:6]
127 return hashlib.md5(self.name.encode()).hexdigest()[:6]
128
128
129 def get_parent(self):
129 def get_parent(self):
130 return self.parent
130 return self.parent
131
131
132 def get_all_parents(self):
132 def get_all_parents(self):
133 parents = list()
133 parents = list()
134 parent = self.get_parent()
134 parent = self.get_parent()
135 if parent and parent not in parents:
135 if parent and parent not in parents:
136 parents.insert(0, parent)
136 parents.insert(0, parent)
137 parents = parent.get_all_parents() + parents
137 parents = parent.get_all_parents() + parents
138
138
139 return parents
139 return parents
140
140
141 def get_children(self):
141 def get_children(self):
142 return self.children
142 return self.children
General Comments 0
You need to be logged in to leave comments. Login now