aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2011-05-02 21:41:28 -0400
committerbnewbold <bnewbold@robocracy.org>2011-05-02 21:41:28 -0400
commita8cf5584204d77bd3f234fe579844ca84bb3558d (patch)
treed45ad752f2d514ff78fb10877565db3e94e5bde1
parentcb7110e3694bba239f7754f275c071341bba1088 (diff)
downloadpiccast-a8cf5584204d77bd3f234fe579844ca84bb3558d.zip
piccast-a8cf5584204d77bd3f234fe579844ca84bb3558d.tar.gz
basic json keyword search
-rw-r--r--piccast/feeds/models.py39
-rw-r--r--piccast/feeds/views.py22
-rw-r--r--piccast/urls.py1
3 files changed, 62 insertions, 0 deletions
diff --git a/piccast/feeds/models.py b/piccast/feeds/models.py
index cbc12e4..0ec24f1 100644
--- a/piccast/feeds/models.py
+++ b/piccast/feeds/models.py
@@ -126,3 +126,42 @@ class PicSet(models.Model):
}
+# The below search code comes from Julien Phalip
+
+import re
+from django.db.models import Q
+
+def normalize_query(query_string,
+ findterms=re.compile(r'"([^"]+)"|(\S+)').findall,
+ normspace=re.compile(r'\s{2,}').sub):
+ ''' Splits the query string in invidual keywords, getting rid of unecessary spaces
+ and grouping quoted words together.
+ Example:
+
+ >>> normalize_query(' some random words "with quotes " and spaces')
+ ['some', 'random', 'words', 'with quotes', 'and', 'spaces']
+
+ '''
+ return [normspace(' ', (t[0] or t[1]).strip()) for t in findterms(query_string)]
+
+def get_query(query_string, search_fields):
+ ''' Returns a query, that is a combination of Q objects. That combination
+ aims to search keywords within a model by testing the given search fields.
+
+ '''
+ query = None # Query to search for every search term
+ terms = normalize_query(query_string)
+ for term in terms:
+ or_query = None # Query to search for a given term in each field
+ for field_name in search_fields:
+ q = Q(**{"%s__icontains" % field_name: term})
+ if or_query is None:
+ or_query = q
+ else:
+ or_query = or_query | q
+ if query is None:
+ query = or_query
+ else:
+ query = query & or_query
+ return query
+
diff --git a/piccast/feeds/views.py b/piccast/feeds/views.py
index 1c26d12..d434818 100644
--- a/piccast/feeds/views.py
+++ b/piccast/feeds/views.py
@@ -35,3 +35,25 @@ def pics_by_set(request, req_picset):
pics = Pic.objects.filter(set=req_picset).order_by('id')
return HttpResponse(json.dumps({'list':[p.serializable() for p in pics]}, indent=2), mimetype="application/json")
+def json_search(request):
+ query_string = ''
+ found_feeds = []
+ found_picsets = []
+ found_pics = []
+ query_keywords = []
+ if ('q' in request.GET) and request.GET['q'].strip():
+ query_string = request.GET['q']
+ feed_query = get_query(query_string, ['title', 'description',])
+ picset_query = get_query(query_string, ['title', 'description','keywords'])
+ pic_query = get_query(query_string, ['title', 'description','keywords'])
+ found_feeds = PicFeed.objects.filter(feed_query).order_by('-created')[:6]
+ found_picsets = PicSet.objects.filter(picset_query).order_by('-created')[:6]
+ found_pics = PicSet.objects.filter(pic_query).order_by('-created')[:6]
+ query_keywords = normalize_query(query_string)
+
+ return HttpResponse(json.dumps({'matching_feeds':[feed.serializable() for feed in found_feeds],
+ 'matching_picsets':[picset.serializable() for picset in found_picsets],
+ 'matching_pics':[pic.serializable() for pic in found_pics],
+ 'query_keywords':query_keywords,
+ }, indent=2), mimetype="application/json")
+
diff --git a/piccast/urls.py b/piccast/urls.py
index daa67da..51ba2d6 100644
--- a/piccast/urls.py
+++ b/piccast/urls.py
@@ -23,6 +23,7 @@ urlpatterns = patterns('',
(r'^json/pics_by_set/(\d+)/', 'feeds.views.pics_by_set'),
(r'^json/sets_by_feed/(\d+)/', 'feeds.views.sets_by_feed'),
(r'^json/sets_by_feed/([-\w]+)/', 'feeds.views.sets_by_feedslug'),
+ (r'^json/search', 'feeds.views.json_search'),
(r'^$', 'feeds.views.basic_frontpage'),
)