##// END OF EJS Templates
Speed up tag localization
neko259 -
r1889:2e613ec2 default
parent child Browse files
Show More
@@ -1,196 +1,201 b''
1 1 import hashlib
2 2 import re
3 3
4 4 from boards.models.attachment import FILE_TYPES_IMAGE
5 5 from django.template.loader import render_to_string
6 6 from django.db import models
7 from django.db.models import Count
7 from django.db.models import Count, Q
8 8 from django.core.urlresolvers import reverse
9 9 from django.utils.translation import get_language
10 10
11 11 from boards.models import Attachment
12 12 from boards.models.base import Viewable
13 13 from boards.models.thread import STATUS_ACTIVE, STATUS_BUMPLIMIT, STATUS_ARCHIVE
14 14 from boards.utils import cached_result
15 15 import boards
16 16
17 17 __author__ = 'neko259'
18 18
19 19
20 20 RELATED_TAGS_COUNT = 5
21 21 DEFAULT_LOCALE = 'default'
22 22
23 23
24 24 class TagAlias(models.Model, Viewable):
25 25 class Meta:
26 26 app_label = 'boards'
27 27 ordering = ('name',)
28 28
29 29 name = models.CharField(max_length=100, db_index=True)
30 30 locale = models.CharField(max_length=10, db_index=True)
31 31
32 32 parent = models.ForeignKey('Tag', null=True, blank=True,
33 33 related_name='aliases')
34 34
35 35
36 36 class TagManager(models.Manager):
37 37 def get_not_empty_tags(self):
38 38 """
39 39 Gets tags that have non-archived threads.
40 40 """
41 41
42 42 return self.annotate(num_threads=Count('thread_tags'))\
43 43 .filter(num_threads__gt=0)\
44 44 .filter(aliases__locale=DEFAULT_LOCALE)\
45 45 .order_by('aliases__name')
46 46
47 47 def get_tag_url_list(self, tags: list) -> str:
48 48 """
49 49 Gets a comma-separated list of tag links.
50 50 """
51 51
52 52 return ', '.join([tag.get_view() for tag in tags])
53 53
54 54 def get_by_alias(self, alias):
55 55 tag = None
56 56 aliases = TagAlias.objects.filter(name=alias).all()
57 57 if aliases:
58 58 tag = aliases[0].parent
59 59
60 60 return tag
61 61
62 62 def get_or_create_with_alias(self, name, required=False):
63 63 tag = self.get_by_alias(name)
64 64 created = False
65 65 if not tag:
66 66 tag = self.create(required=required)
67 67 TagAlias.objects.create(name=name, locale=DEFAULT_LOCALE, parent=tag)
68 68 created = True
69 69 return tag, created
70 70
71 71
72 72 class Tag(models.Model, Viewable):
73 73 """
74 74 A tag is a text node assigned to the thread. The tag serves as a board
75 75 section. There can be multiple tags for each thread
76 76 """
77 77
78 78 objects = TagManager()
79 79
80 80 class Meta:
81 81 app_label = 'boards'
82 82
83 83 required = models.BooleanField(default=False, db_index=True)
84 84 description = models.TextField(blank=True)
85 85
86 86 parent = models.ForeignKey('Tag', null=True, blank=True,
87 87 related_name='children')
88 88
89 89 def get_name(self):
90 90 return self.aliases.get(locale=DEFAULT_LOCALE).name
91 91
92 92 def __str__(self):
93 93 return self.get_name()
94 94
95 95 def is_empty(self) -> bool:
96 96 """
97 97 Checks if the tag has some threads.
98 98 """
99 99
100 100 return self.get_thread_count() == 0
101 101
102 102 def get_thread_count(self, status=None) -> int:
103 103 threads = self.get_threads()
104 104 if status is not None:
105 105 threads = threads.filter(status=status)
106 106 return threads.count()
107 107
108 108 def get_active_thread_count(self) -> int:
109 109 return self.get_thread_count(status=STATUS_ACTIVE)
110 110
111 111 def get_bumplimit_thread_count(self) -> int:
112 112 return self.get_thread_count(status=STATUS_BUMPLIMIT)
113 113
114 114 def get_archived_thread_count(self) -> int:
115 115 return self.get_thread_count(status=STATUS_ARCHIVE)
116 116
117 117 def get_absolute_url(self):
118 118 return reverse('tag', kwargs={'tag_name': self.get_name()})
119 119
120 120 def get_threads(self):
121 121 return self.thread_tags.order_by('-bump_time')
122 122
123 123 def is_required(self):
124 124 return self.required
125 125
126 126 def _get_locale_cache_key(self):
127 127 return '{}_{}'.format(self.id, get_language())
128 128
129 129 @cached_result(key_method=_get_locale_cache_key)
130 130 def get_view(self):
131 131 locale = get_language()
132 132
133 try:
134 localized_tag_name = self.aliases.get(locale=locale).name
135 except TagAlias.DoesNotExist:
136 localized_tag_name = ''
133 aliases = self.aliases.filter(Q(locale=locale) | Q(locale=DEFAULT_LOCALE))
134
135 localized_tag_name = None
136 default_tag_name = None
137 137
138 default_name = self.get_name()
138 for alias in aliases:
139 if alias.locale == locale:
140 localized_tag_name = alias.name
141 elif alias.locale == DEFAULT_LOCALE:
142 default_tag_name = alias.name
139 143
140 name = '{} ({})'.format(default_name, localized_tag_name) if localized_tag_name else default_name
144 name = '{} ({})'.format(default_tag_name, localized_tag_name) \
145 if localized_tag_name else default_tag_name
141 146 link = '<a class="tag" href="{}">{}</a>'.format(
142 147 self.get_absolute_url(), name)
143 148 if self.is_required():
144 149 link = '<b>{}</b>'.format(link)
145 150 return link
146 151
147 152 @cached_result()
148 153 def get_post_count(self):
149 154 return self.get_threads().aggregate(num_posts=Count('replies'))['num_posts']
150 155
151 156 def get_description(self):
152 157 return self.description
153 158
154 159 def get_random_image_post(self, status=[STATUS_ACTIVE, STATUS_BUMPLIMIT]):
155 160 posts = boards.models.Post.objects.filter(attachments__mimetype__in=FILE_TYPES_IMAGE)\
156 161 .annotate(images_count=Count(
157 162 'attachments')).filter(images_count__gt=0, thread__tags__in=[self])
158 163 if status is not None:
159 164 posts = posts.filter(thread__status__in=status)
160 165 return posts.order_by('?').first()
161 166
162 167 def get_first_letter(self):
163 168 name = self.get_name()
164 169 return name and name[0] or ''
165 170
166 171 def get_related_tags(self):
167 172 return set(Tag.objects.filter(thread_tags__in=self.get_threads()).exclude(
168 173 id=self.id).order_by('?')[:RELATED_TAGS_COUNT])
169 174
170 175 @cached_result()
171 176 def get_color(self):
172 177 """
173 178 Gets color hashed from the tag name.
174 179 """
175 180 return hashlib.md5(self.get_name().encode()).hexdigest()[:6]
176 181
177 182 def get_parent(self):
178 183 return self.parent
179 184
180 185 def get_all_parents(self):
181 186 parents = list()
182 187 parent = self.get_parent()
183 188 if parent and parent not in parents:
184 189 parents.insert(0, parent)
185 190 parents = parent.get_all_parents() + parents
186 191
187 192 return parents
188 193
189 194 def get_children(self):
190 195 return self.children
191 196
192 197 def get_images(self):
193 198 return Attachment.objects.filter(
194 199 attachment_posts__thread__tags__in=[self]).filter(
195 200 mimetype__in=FILE_TYPES_IMAGE).order_by('-attachment_posts__pub_time')
196 201
General Comments 0
You need to be logged in to leave comments. Login now