-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
/
taggable.py
65 lines (56 loc) · 2.21 KB
/
taggable.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
from taggit.models import Tag
from django.contrib.contenttypes.models import ContentType
from django.db.models import Count, Q
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from wagtail.wagtailsearch import Indexed, Search
class TagSearchable(Indexed):
"""
Mixin to provide a 'search' method, searching on the 'title' field and tags,
for models that provide those things.
"""
indexed_fields = {
'title': {
'type': 'string',
'analyzer': 'edgengram_analyzer',
'boost': 10,
},
'get_tags': {
'type': 'string',
'analyzer': 'edgengram_analyzer',
'boost': 10,
},
}
@property
def get_tags(self):
return ' '.join([tag.name for tag in self.tags.all()])
@classmethod
def search(cls, q, results_per_page=None, page=1, prefetch_tags=False, filters={}):
# Run search query
if prefetch_tags:
results = Search().search(q, cls, prefetch_related=['tagged_items__tag'], filters=filters)
else:
results = Search().search(q, cls, filters=filters)
# If results_per_page is set, return a paginator
if results_per_page is not None:
paginator = Paginator(results, results_per_page)
try:
return paginator.page(page)
except PageNotAnInteger:
return paginator.page(1)
except EmptyPage:
return paginator.page(paginator.num_pages)
else:
return results
def prefetched_tags(self):
# a hack to do the equivalent of self.tags.all() but take advantage of the
# prefetch_related('tagged_items__tag') in the above search method, so that we can
# output the list of tags on each result without doing a further query
return [tagged_item.tag for tagged_item in self.tagged_items.all()]
@classmethod
def popular_tags(cls):
content_type = ContentType.objects.get_for_model(cls)
return Tag.objects.filter(
taggit_taggeditem_items__content_type=content_type
).annotate(
item_count=Count('taggit_taggeditem_items')
).order_by('-item_count')[:10]