diff --git a/apps/dynamic_search/__init__.py b/apps/dynamic_search/__init__.py index eea43074dc..2d3d73c5f4 100644 --- a/apps/dynamic_search/__init__.py +++ b/apps/dynamic_search/__init__.py @@ -8,5 +8,7 @@ search_again = {'text': _(u'search again'), 'view': 'search_again', 'famfam': 'a register_sidebar_template(['search', 'search_advanced'], 'search_help.html') -register_links(['search', 'search_advanced'], [search, search_advanced], menu_name='form_header') +register_links(['search', 'search_advanced', 'results'], [search, search_advanced], menu_name='form_header') register_links(['results'], [search_again], menu_name='sidebar') + +register_sidebar_template(['search', 'search_advanced', 'results'], 'recent_searches.html') diff --git a/apps/dynamic_search/admin.py b/apps/dynamic_search/admin.py new file mode 100644 index 0000000000..3592e29bc6 --- /dev/null +++ b/apps/dynamic_search/admin.py @@ -0,0 +1,11 @@ +from django.contrib import admin + +from dynamic_search.models import RecentSearch + + +class RecentSearchAdmin(admin.ModelAdmin): + list_display = ('user', 'query', 'datetime_created', 'hits') + list_display_links = ('user', 'query', 'datetime_created', 'hits') + readonly_fields = ('user', 'query', 'datetime_created', 'hits') + +admin.site.register(RecentSearch, RecentSearchAdmin) diff --git a/apps/dynamic_search/conf/settings.py b/apps/dynamic_search/conf/settings.py index b9ef4077ea..cc57a5cb1e 100644 --- a/apps/dynamic_search/conf/settings.py +++ b/apps/dynamic_search/conf/settings.py @@ -10,5 +10,6 @@ register_settings( settings=[ {'name': u'SHOW_OBJECT_TYPE', 'global_name': u'SEARCH_SHOW_OBJECT_TYPE', 'default': True, 'hidden': True}, {'name': u'LIMIT', 'global_name': u'SEARCH_LIMIT', 'default': 100, 'description': _(u'Maximum amount search hits to fetch and display.')}, + {'name': u'RECENT_COUNT', 'global_name': u'SEARCH_RECENT_COUNT', 'default': 5, 'description': _(u'Maximum number of search queries to remember per user.')}, ] ) diff --git a/apps/dynamic_search/managers.py b/apps/dynamic_search/managers.py new file mode 100644 index 0000000000..74d2cd5de0 --- /dev/null +++ b/apps/dynamic_search/managers.py @@ -0,0 +1,15 @@ +from datetime import datetime + +from django.db import models + +from dynamic_search.conf.settings import RECENT_COUNT + + +class RecentSearchManager(models.Manager): + def add_query_for_user(self, user, query, hits): + new_recent, created = self.model.objects.get_or_create(user=user, query=query) + new_recent.hits = hits + new_recent.save() + to_delete = self.model.objects.filter(user=user)[RECENT_COUNT:] + for recent_to_delete in to_delete: + recent_to_delete.delete() diff --git a/apps/dynamic_search/models.py b/apps/dynamic_search/models.py index 71a8362390..488cd8fa2b 100644 --- a/apps/dynamic_search/models.py +++ b/apps/dynamic_search/models.py @@ -1,3 +1,61 @@ -from django.db import models +import urlparse -# Create your models here. +from datetime import datetime + +from django.db import models +from django.utils.translation import ugettext as _ +from django.contrib.auth.models import User +from django.core.urlresolvers import reverse + +from dynamic_search.managers import RecentSearchManager +from dynamic_search.api import registered_search_dict + + +class RecentSearch(models.Model): + """ + Keeps a list of the n most recent search keywords for a given user + """ + user = models.ForeignKey(User, verbose_name=_(u'user'), editable=False) + query = models.TextField(verbose_name=_(u'query'), editable=False) + datetime_created = models.DateTimeField(verbose_name=_(u'datetime created'), editable=False) + hits = models.IntegerField(verbose_name=_(u'hits'), editable=False) + + objects = RecentSearchManager() + + def __unicode__(self): + query_dict = urlparse.parse_qs(self.query) + if 'q' in query_dict: + # Is a simple search + display_string = u' '.join(query_dict['q']) + else: + # Advanced search + advanced_string = [] + for key, value in query_dict.items(): + # Get model name + model, field_name = key.split('__', 1) + model_entry = registered_search_dict.get(model, {}) + if model_entry: + # Find the field name title + for model_field in model_entry.get('fields', [{}]): + if model_field.get('name') == field_name: + advanced_string.append(u'%s: %s' % (model_field.get('title', model_field['name']), u' '.join(value))) + + display_string = u', '.join(advanced_string) + + return u'%s (%s)' % (display_string, self.hits) + + def save(self, *args, **kwargs): + self.datetime_created = datetime.now() + super(RecentSearch, self).save(*args, **kwargs) + + def url(self): + view = 'results' if self.is_advanced() else 'search' + return '%s?%s' % (reverse(view), self.query) + + def is_advanced(self): + return 'q' not in urlparse.parse_qs(self.query) + + class Meta: + ordering = ('-datetime_created',) + verbose_name = _(u'recent search') + verbose_name_plural = _(u'recent searches') diff --git a/apps/dynamic_search/templates/recent_searches.html b/apps/dynamic_search/templates/recent_searches.html new file mode 100644 index 0000000000..e35c29e6da --- /dev/null +++ b/apps/dynamic_search/templates/recent_searches.html @@ -0,0 +1,2 @@ +{% load search_tags %} +{% recent_searches_template %} diff --git a/apps/dynamic_search/templatetags/search_tags.py b/apps/dynamic_search/templatetags/search_tags.py index 16a77726a2..a2866b215d 100644 --- a/apps/dynamic_search/templatetags/search_tags.py +++ b/apps/dynamic_search/templatetags/search_tags.py @@ -3,6 +3,8 @@ from django.template import Library from django.utils.translation import ugettext as _ from dynamic_search.forms import SearchForm +from dynamic_search.models import RecentSearch +from dynamic_search.conf.settings import RECENT_COUNT register = Library() @@ -19,3 +21,24 @@ def search_form(context): 'submit_icon_famfam': 'zoom', }) return context + + +@register.inclusion_tag('generic_subtemplate.html', takes_context=True) +def recent_searches_template(context): + recent_searches = RecentSearch.objects.filter(user=context['user']) + + context.update({ + 'request': context['request'], + 'MEDIA_URL': context['MEDIA_URL'], + 'side_bar': True, + 'title': _(u'recent searches (maximum of %d)') % RECENT_COUNT, + 'paragraphs': [ + u'%(text)s' % { + 'text': rs, + 'url': rs.url(), + 'icon': 'zoom_in' if rs.is_advanced() else 'zoom', + } for rs in recent_searches + ] + }) + + return context diff --git a/apps/dynamic_search/views.py b/apps/dynamic_search/views.py index 7d12d30fc8..5030b52f6b 100644 --- a/apps/dynamic_search/views.py +++ b/apps/dynamic_search/views.py @@ -7,7 +7,9 @@ from django.contrib import messages from django.conf import settings from django.http import HttpResponseRedirect from django.core.urlresolvers import reverse +from django.utils.http import urlencode +from dynamic_search.models import RecentSearch from dynamic_search.api import perform_search from dynamic_search.forms import SearchForm, AdvancedSearchForm from dynamic_search.conf.settings import SHOW_OBJECT_TYPE @@ -25,9 +27,6 @@ def results(request, extra_context=None): 'search_results_limit': LIMIT, }) - if extra_context: - context.update(extra_context) - try: response = perform_search(request.GET) if response['shown_result_count'] != response['result_count']: @@ -36,13 +35,20 @@ def results(request, extra_context=None): 'result_count': response['result_count']} else: title = _(u'results') + + if extra_context: + context.update(extra_context) + query = urlencode(dict(request.GET.items())) + + if query: + RecentSearch.objects.add_query_for_user(request.user, query, response['result_count']) + context.update({ 'found_entries': response['model_list'], 'object_list': response['flat_list'], 'title': title, 'time_delta': response['elapsed_time'], }) - except Exception, e: if settings.DEBUG: raise