Improve IndexableObject class methods

This commit is contained in:
Roberto Rosario
2012-04-12 02:04:50 -04:00
parent 97ae34a06d
commit 520d6cc3af
10 changed files with 107 additions and 105 deletions

View File

@@ -15,25 +15,24 @@ from .models import IndexableObject
logger = logging.getLogger(__name__)
search = {'text': _(u'search'), 'view': 'search', 'famfam': 'zoom'}
search_advanced = {'text': _(u'advanced search'), 'view': 'search_advanced', 'famfam': 'zoom_in'}
search_again = {'text': _(u'search again'), 'view': 'search_again', 'famfam': 'arrow_undo'}
#search_advanced = {'text': _(u'advanced search'), 'view': 'search_advanced', 'famfam': 'zoom_in'}
#search_again = {'text': _(u'search again'), 'view': 'search_again', 'famfam': 'arrow_undo'}
register_sidebar_template(['search', 'search_advanced'], 'search_help.html')
#register_sidebar_template(['search', 'search_advanced'], 'search_help.html')
register_sidebar_template(['search'], 'search_help.html')
register_links(['search', 'search_advanced', 'results'], [search, search_advanced], menu_name='form_header')
register_links(['results'], [search_again], menu_name='sidebar')
#register_links(['search', 'search_advanced', 'results'], [search, search_advanced], menu_name='form_header')
register_links(['search'], [search], menu_name='form_header')
#register_links(['results'], [search_again], menu_name='sidebar')
register_sidebar_template(['search', 'search_advanced', 'results'], 'recent_searches.html')
#register_sidebar_template(['search', 'search_advanced', 'results'], 'recent_searches.html')
register_sidebar_template(['search'], 'recent_searches.html')
Document.add_to_class('mark_indexable', lambda obj: IndexableObject.objects.mark_indexable(obj))
def mark_dirty(obj):
IndexableObject.objects.mark_dirty(content_object=obj)
Document.add_to_class('mark_dirty', lambda obj: IndexableObject.objects.mark_dirty(obj))
@receiver(post_update_index, dispatch_uid='clear_dirty_indexables')
def clear_dirty_indexables(sender, **kwargs):
@receiver(post_update_index, dispatch_uid='clear_pending_indexables')
def clear_pending_indexables(sender, **kwargs):
logger.debug('Clearing all indexable flags post update index signal')
IndexableObject.objects.clear_all()

View File

@@ -1,6 +1,8 @@
from __future__ import absolute_import
from django.contrib import admin
from dynamic_search.models import RecentSearch, IndexableObject
from .models import RecentSearch, IndexableObject
class RecentSearchAdmin(admin.ModelAdmin):

View File

@@ -3,11 +3,16 @@ from __future__ import absolute_import
from django import forms
from django.utils.translation import ugettext_lazy as _
from haystack.forms import SearchForm
from haystack.forms import SearchForm as BasicSearchForm
from .api import registered_search_dict
class SearchForm(BasicSearchForm):
pass
"""
class AdvancedSearchForm(SearchForm):
def __init__(self, *args, **kwargs):
super(AdvancedSearchForm, self).__init__(*args, **kwargs)
@@ -37,3 +42,4 @@ class AdvancedSearchForm(SearchForm):
def search(self):
sqs = super(ModelSearchForm, self).search()
return sqs.models(*self.get_models())
"""

View File

@@ -1,32 +1,59 @@
import urlparse
from urlparse import urlparse, parse_qs
from urllib import unquote_plus
from django.db import models
from django.utils.simplejson import dumps, loads, JSONEncoder
from django.db.models import Manager
from django.utils.http import urlencode
from django.contrib.auth.models import AnonymousUser
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.utils.encoding import smart_unicode, smart_str
from dynamic_search.conf.settings import RECENT_COUNT
class RecentSearchManager(models.Manager):
def add_query_for_user(self, user, query, hits):
parsed_query = urlparse.parse_qs(query)
for key, value in parsed_query.items():
parsed_query[key] = ' '.join(value)
class RecentSearchManager(Manager):
def add_query_for_user(self, search_view):#user, url, hits):
query_dict = parse_qs(unquote_plus(smart_str(urlparse(search_view.request.get_full_path()).query)))
print 'query_dict', query_dict
print 'serial', dumps(query_dict)
#parsed_query = urlparse.parse_qs(query)
#for key, value in parsed_query.items():
# parsed_query[key] = ' '.join(value)#
if 'q=' in query:
# Is a simple query
if not parsed_query.get('q'):
# Don't store empty simple searches
return
else:
# Cleanup query string and only store the q parameter
parsed_query = {'q': parsed_query['q']}
#if 'q=' in query:
# # Is a simple query
# if not parsed_query.get('q'):
# # Don't store empty simple searches
# return
# else:
# # Cleanup query string and only store the q parameter
# parsed_query = {'q': parsed_query['q']}
if parsed_query and not isinstance(user, AnonymousUser):
if query_dict and not isinstance(search_view.request.user, AnonymousUser):
# If the URL query has at least one variable with a value
new_recent, created = self.model.objects.get_or_create(user=user, query=urlencode(parsed_query), defaults={'hits': hits})
new_recent.hits = hits
new_recent, created = self.model.objects.get_or_create(user=search_view.request.user, query=dumps(query_dict), defaults={'hits': 0})
new_recent.hits = search_view.results.count()
new_recent.save()
to_delete = self.model.objects.filter(user=user)[RECENT_COUNT:]
to_delete = self.model.objects.filter(user=search_view.request.user)[RECENT_COUNT:]
for recent_to_delete in to_delete:
recent_to_delete.delete()
class IndexableObjectManager(Manager):
def get_indexables(self, datetime=None):
if datetime:
return self.model.objects.filter(datetime__gte=datetime)
else:
return self.model.objects.all()
def get_indexables_pk_list(self, datetime=None):
return self.get_indexables(datetime).values_list('object_id', flat=True)
def mark_indexable(self, obj):
content_type = ContentType.objects.get_for_model(obj)
self.model.objects.get_or_create(content_type=content_type, object_id=obj.pk)
def clear_all(self):
self.model.objects.all().delete()

View File

@@ -9,11 +9,12 @@ from django.utils.translation import ugettext as _
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.utils.encoding import smart_unicode, smart_str
from django.utils.translation import ugettext_lazy as _
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
from django.utils.translation import ugettext_lazy as _
from django.utils.simplejson import loads
from .managers import RecentSearchManager
from .managers import RecentSearchManager, IndexableObjectManager
from .api import registered_search_dict
@@ -29,36 +30,27 @@ class RecentSearch(models.Model):
objects = RecentSearchManager()
def __unicode__(self):
query_dict = urlparse.parse_qs(urllib.unquote_plus(smart_str(self.query)))
if 'q' in query_dict:
# Is a simple search
display_string = smart_unicode(' '.join(query_dict['q']))
if self.is_advanced():
return u'%s (%s)' % (self.get_query(), self.hits)
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']), smart_unicode(' '.join(value))))
display_string = u', '.join(advanced_string)
return u'%s (%s)' % (display_string, self.hits)
return u'%s (%s)' % (self.get_query().get('q'), self.hits)
def save(self, *args, **kwargs):
self.datetime_created = datetime.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 readable_query(self):
# return self.
#def url(self):
# view = 'results' if self.is_advanced() else 'search'
# return '%s?%s' % (reverse(view), self.query)
def get_query(self):
return loads(self.query)
def is_advanced(self):
return 'q' not in urlparse.parse_qs(self.query)
return 'q' not in self.get_query()
class Meta:
ordering = ('-datetime_created',)
@@ -66,32 +58,14 @@ class RecentSearch(models.Model):
verbose_name_plural = _(u'recent searches')
class IndexableObjectManager(models.Manager):
def get_dirty(self, datetime=None):
if datetime:
return self.model.objects.filter(datetime__gte=datetime)
else:
return self.model.objects.all()
def get_dirty_pk_list(self, datetime=None):
return self.get_dirty(datetime).values_list('object_id', flat=True)
def mark_dirty(self, obj):
content_type = ContentType.objects.get_for_model(obj)
self.model.objects.get_or_create(content_type=content_type, object_id=obj.pk)
def clear_all(self):
self.model.objects.all().delete()
class IndexableObject(models.Model):
"""
Store a list of object links that have been modified and are
meant to be indexed in the next search index update
"""
datetime = models.DateTimeField(verbose_name=_(u'date time'))
content_type = models.ForeignKey(ContentType, blank=True, null=True)
object_id = models.PositiveIntegerField(blank=True, null=True)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
objects = IndexableObjectManager()

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import
import datetime
import logging
from unidecode import unidecode
from haystack import indexes
@@ -9,25 +10,16 @@ from documents.models import Document
from .models import IndexableObject
logger = logging.getLogger(__name__)
'''
comment = models.TextField(blank=True, verbose_name=_(u'comment'))
checksum = models.TextField(blank=True, null=True, verbose_name=_(u'checksum'), editable=False)
page_label = models.CharField(max_length=32, blank=True, null=True, verbose_name=_(u'page label'))
page_number = models.PositiveIntegerField(default=1, editable=False, verbose_name=_(u'page number'), db_index=True)
# Register the fields that will be searchable
register('document', Document, _(u'document'), [
{'name': u'document_type__name', 'title': _(u'Document type')},
{'name': u'documentversion__mimetype', 'title': _(u'MIME type')},
{'name': u'documentversion__filename', 'title': _(u'Filename')},
{'name': u'documentmetadata__value', 'title': _(u'Metadata value')},
{'name': u'documentversion__documentpage__content', 'title': _(u'Content')},
{'name': u'description', 'title': _(u'Description')},
{'name': u'tags__name', 'title': _(u'Tags')},
{'name': u'comments__comment', 'title': _(u'Comments')},
]
)
#register(Document, _(u'document'), ['document_type__name', 'file_mimetype', 'documentmetadata__value', 'documentpage__content', 'description', {'field_name':'file_filename', 'comparison':'iexact'}])
'''
@@ -38,8 +30,6 @@ class DocumentIndex(indexes.SearchIndex, indexes.Indexable):
return Document
def build_queryset(self, start_date=None, end_date=None):
print "DIRTY", IndexableObject.objects.get_dirty_pk_list()
#return self.get_model().objects.filter(date_added__lte=datetime.datetime.now())
return self.get_model().objects.filter(pk__in=IndexableObject.objects.get_dirty_pk_list())
#return self.get_model().objects.all()
indexable_list = IndexableObject.objects.get_indexables_pk_list()
logger.debug('indexable list: %s' % indexable_list)
return self.get_model().objects.filter(pk__in=indexable_list)

View File

@@ -3,7 +3,6 @@
{% block title %} :: {% trans "Search results" %}{% endblock %}
{% block content %}
{% if form %}
{% include "search_results_subtemplate.html" %}
{% endif %}

View File

@@ -20,7 +20,7 @@ def search_form(context):
'submit_label': _(u'Search'),
'submit_icon_famfam': 'zoom',
})
return context
return ''
@register.inclusion_tag('generic_subtemplate.html', takes_context=True)
@@ -34,7 +34,7 @@ def recent_searches_template(context):
'paragraphs': [
u'<a href="%(url)s"><span class="famfam active famfam-%(icon)s"></span>%(text)s</a>' % {
'text': rs,
'url': rs.url(),
'url': reverse('search'),
'icon': 'zoom_in' if rs.is_advanced() else 'zoom',
} for rs in recent_searches
]

View File

@@ -3,11 +3,10 @@ from django.conf.urls.defaults import patterns, url
from haystack.forms import SearchForm
from .views import CustomSearchView
from .forms import AdvancedSearchForm
urlpatterns = patterns('dynamic_search.views',
url(r'^$', CustomSearchView(form_class=SearchForm), (), 'search'),
url(r'^advanced/$', CustomSearchView(form_class=AdvancedSearchForm), (), 'search_advanced'),
url(r'^again/$', 'search_again', (), 'search_again'),
url(r'^results/$', 'results', (), 'results'),
#url(r'^advanced/$', CustomSearchView(form_class=AdvancedSearchForm), (), 'search_advanced'),
#url(r'^again/$', 'search_again', (), 'search_again'),
#url(r'^results/$', 'results', (), 'results'),
)

View File

@@ -16,8 +16,11 @@ from common.utils import encapsulate
from dynamic_search.models import RecentSearch
from dynamic_search.api import perform_search
from dynamic_search.forms import SearchForm, AdvancedSearchForm
#TODO: DEPRECATED
from dynamic_search.conf.settings import SHOW_OBJECT_TYPE
#TODO: DEPRECATED?
from dynamic_search.conf.settings import LIMIT
@@ -47,11 +50,13 @@ class CustomSearchView(SearchView):
'elapsed_time': unicode(datetime.datetime.now() - self.start_time).split(':')[2],
'object_list_object_name': 'object',
}
RecentSearch.objects.add_query_for_user(self)
context.update(self.extra_context())
return render_to_response(self.template, context, context_instance=self.context_class(self.request))
"""
def results(request, extra_context=None):
context = {}
@@ -141,3 +146,4 @@ def search(request, advanced=False):
def search_again(request):
query = urlparse.urlparse(request.META.get('HTTP_REFERER', u'/')).query
return HttpResponseRedirect('%s?%s' % (reverse('search_advanced'), query))
"""