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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138 | ##################
# models.py
##################
from search import SearchQuerySet
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
# Make sure to create this fulltext index!
# create fulltext index searchable_media on searchable_searchablemedia (search_text);
#
class SearchableMediaManager(models.Manager):
def search(self,query):
return SearchQuerySet(self.model,['search_text']).search(query)
class SearchableMedia(models.Model):
objects=SearchableMediaManager()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type','object_id')
search_text = models.TextField()
def __str__(self):
return "Searchable Content for %s-%s"%(self.content_type.name,self.get_content_object())
def get_content_object(self):
return self.content_object
# for debug for now
class Admin:
pass
def update_terms(object,terms):
sm=None
try:
sm=SearchableMedia.objects.get(content_type=ContentType.objects.get_for_model(object),object_id=object.id)
except SearchableMedia.DoesNotExist:
sm=SearchableMedia(content_type=ContentType.objects.get_for_model(object),object_id=object.id)
if sm:
sm.search_text=terms
sm.save()
##################
# views.py
##################
from django.http import HttpResponseRedirect
from django.shortcuts import render_to_response
from django.template import RequestContext
from models import SearchableMedia
# Create your views here.
def search(request,template="search.html"):
if "keyword" not in request.REQUEST:
return HttpResponseRedirect("/")
results=SearchableMedia.objects.search(request.REQUEST["keyword"])
return render_to_response(template,{"results":results},context_instance=RequestContext(request))
##################
# search.py
##################
from django.db import models, backend
class SearchQuerySet(models.query.QuerySet):
""" Search Query Set courtesy of http://www.mercurytide.com/whitepapers/django-full-text-search/
"""
def __init__(self, model=None, fields=None):
super(SearchQuerySet, self).__init__(model)
self._search_fields = fields
def search(self, query):
meta = self.model._meta
db_operations = backend.DatabaseOperations()
# Get the table name and column names from the model
# in `table_name`.`column_name` style
columns = [meta.get_field(name,
many_to_many=False).column
for name in self._search_fields]
full_names = ["%s.%s" %
(db_operations.quote_name(meta.db_table),
db_operations.quote_name(column))
for column in columns]
# Create the MATCH AGAINST expressions
fulltext_columns = ", ".join(full_names)
match_expr = ("MATCH(%s) AGAINST (%%s)" %
fulltext_columns)
# Add the extra SELECT and WHERE options
return self.extra(select={'relevance': match_expr},
where=[match_expr],
params=[query, query])
##################
# models.py of objects you want included in search
##################
def post_blogentry_save(sender,instance):
update_terms(instance," ".join([instance.title,instance.body]))
dispatcher.connect(post_blogentry_save, sender=BlogEntry, signal=models.signals.post_save)
def post_video_save(sender,instance):
update_terms(instance," ".join([instance.title,instance.body]))
dispatcher.connect(post_video_save, sender=Video, signal=models.signals.post_save)
##################
# Template
##################
{% extends "base.html" %}
{% block content %}
<div id="searchresults">
{% for o in results %}
<div class="searchresult">
{% ifequal o.content_type.name "video" %}
{% with o.content_object as video %}
<!-- Video search result here -->
{% endwith %}
{% endifequal %}
{% ifequal o.content_type.name "blogentry" %}
{% with o.content_object as blogentry %}
<!-- BlogEntry search result here -->
{% endwith %}
{% endifequal %}
</div>
{% endfor %}
</div>
{% endblock %}
|
Comments