# HG changeset patch # User ymh # Date 1360746836 -3600 # Node ID daa526d270442d697c6c473a961839242bb607f7 # Parent 365c73a0e8c1fe6e32c65663a776ed1c13a7af55 correct data import (on tags) add indexation and very first version of serach diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/__init__.py --- a/src/egonomy/__init__.py Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/__init__.py Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,17 @@ +VERSION = (0, 0, 0, "alpha", 0) + +VERSION_STR = unicode(".".join(map(lambda i:"%02d" % (i,), VERSION[:2]))) + + +def get_version(): + version = '%s.%s' % (VERSION[0], VERSION[1]) + if VERSION[2]: + version = '%s.%s' % (version, VERSION[2]) + if VERSION[3:] == ('alpha', 0): + version = '%s pre-alpha' % version + else: + if VERSION[3] != 'final': + version = '%s %s %s' % (version, VERSION[3], VERSION[4]) + return version + +__version__ = get_version() diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/config.py.tmpl --- a/src/egonomy/config.py.tmpl Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/config.py.tmpl Wed Feb 13 10:13:56 2013 +0100 @@ -20,6 +20,14 @@ } } +HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': 'egonomy.search_indexes.backends.elasticsearch_backend.ElasticsearchSearchEngine', + 'URL': 'http://127.0.0.1:9200/', + 'INDEX_NAME': 'egonomy', + }, +} + # Local time zone for this installation. Choices can be found here: # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # although not all choices may be available on all operating systems. @@ -122,3 +130,5 @@ 'ENGINE': 'haystack.backends.simple_backend.SimpleEngine', }, } + +IMAGES_PER_PAGE = 32 diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/management/commands/importRmn.py --- a/src/egonomy/management/commands/importRmn.py Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/management/commands/importRmn.py Wed Feb 13 10:13:56 2013 +0100 @@ -203,7 +203,7 @@ site = self.__safe_get(urow, 'SITE'), lieu = self.__safe_get(urow, 'LIEU'), localisation = self.__safe_get(urow, 'LOCALISATION'), - mots_cles = self.__safe_get(urow, 'MOT_CLES') + mots_cles = self.__safe_get(urow, 'MOTS_CLES') ) img_info_obj = None diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/migrations/0001_initial.py --- a/src/egonomy/migrations/0001_initial.py Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/migrations/0001_initial.py Wed Feb 13 10:13:56 2013 +0100 @@ -1,15 +1,13 @@ # -*- coding: utf-8 -*- -import datetime from south.db import db from south.v2 import SchemaMigration -from django.db import models class Migration(SchemaMigration): def forwards(self, orm): # Adding model 'ImageMetadata' - db.create_table(u'egonomy_imagemetadata', ( + db.create_table(u'egonomy_imagemetadata', ( #@UndefinedVariable ('id', self.gf('django.db.models.fields.CharField')(max_length=15, primary_key=True)), ('date_inserted', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), ('date_modified', self.gf('django.db.models.fields.DateTimeField')(auto_now=True, blank=True)), @@ -36,10 +34,10 @@ ('description_pertimm', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), ('thesaurus_pertimm', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), )) - db.send_create_signal(u'egonomy', ['ImageMetadata']) + db.send_create_signal(u'egonomy', ['ImageMetadata']) #@UndefinedVariable # Adding model 'ImageInfo' - db.create_table(u'egonomy_imageinfo', ( + db.create_table(u'egonomy_imageinfo', ( #@UndefinedVariable ('id', self.gf('django.db.models.fields.CharField')(max_length=15, primary_key=True)), ('image_file', self.gf('django.db.models.fields.files.ImageField')(max_length=2048)), ('width', self.gf('django.db.models.fields.IntegerField')()), @@ -47,18 +45,18 @@ ('mimetype', self.gf('django.db.models.fields.CharField')(max_length=1024, null=True, blank=True)), ('exif', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), )) - db.send_create_signal(u'egonomy', ['ImageInfo']) + db.send_create_signal(u'egonomy', ['ImageInfo']) #@UndefinedVariable # Adding model 'Image' - db.create_table(u'egonomy_image', ( + db.create_table(u'egonomy_image', ( #@UndefinedVariable ('id', self.gf('django.db.models.fields.CharField')(max_length=15, primary_key=True)), ('metadata', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['egonomy.ImageMetadata'])), ('info', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['egonomy.ImageInfo'], null=True, blank=True)), )) - db.send_create_signal(u'egonomy', ['Image']) + db.send_create_signal(u'egonomy', ['Image']) #@UndefinedVariable # Adding model 'Fragment' - db.create_table(u'egonomy_fragment', ( + db.create_table(u'egonomy_fragment', ( #@UndefinedVariable (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), ('image', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['egonomy.Image'])), ('date_created', self.gf('django.db.models.fields.DateTimeField')(auto_now_add=True, blank=True)), @@ -69,21 +67,21 @@ ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), ('tags', self.gf('django.db.models.fields.TextField')(null=True, blank=True)), )) - db.send_create_signal(u'egonomy', ['Fragment']) + db.send_create_signal(u'egonomy', ['Fragment']) #@UndefinedVariable def backwards(self, orm): # Deleting model 'ImageMetadata' - db.delete_table(u'egonomy_imagemetadata') + db.delete_table(u'egonomy_imagemetadata') #@UndefinedVariable # Deleting model 'ImageInfo' - db.delete_table(u'egonomy_imageinfo') + db.delete_table(u'egonomy_imageinfo') #@UndefinedVariable # Deleting model 'Image' - db.delete_table(u'egonomy_image') + db.delete_table(u'egonomy_image') #@UndefinedVariable # Deleting model 'Fragment' - db.delete_table(u'egonomy_fragment') + db.delete_table(u'egonomy_fragment') #@UndefinedVariable models = { diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/migrations/0002_update_site.py --- a/src/egonomy/migrations/0002_update_site.py Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/migrations/0002_update_site.py Wed Feb 13 10:13:56 2013 +0100 @@ -1,9 +1,6 @@ # -*- coding: utf-8 -*- -import datetime -from south.db import db from south.v2 import DataMigration from django.conf import settings -from django.db import models class Migration(DataMigration): diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/search_indexes/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/search_indexes/__init__.py Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,6 @@ + +from .indexes import FragmentIndex,ImageMetadataIndex +from .processor import EgonomySignalProcessor +from .query_parser import QueryParser + +__all__ = ['FragmentIndex', 'ImageMetadataIndex', 'EgonomySignalProcessor', 'QueryParser'] \ No newline at end of file diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/search_indexes/backends/__init__.py diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/search_indexes/backends/elasticsearch_backend.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/search_indexes/backends/elasticsearch_backend.py Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,131 @@ +# -*- coding: utf-8 -*- +''' +Created on Feb 12, 2013 + +@author: ymh +''' + +from django.db.models.loading import get_model +from egonomy.models import ImageMetadata, Fragment +from haystack.backends import BaseEngine, SearchResult, elasticsearch_backend +from haystack.constants import DJANGO_CT, DJANGO_ID +import datetime + +class ElasticsearchSearchBackend(elasticsearch_backend.ElasticsearchSearchBackend): + + def build_search_kwargs(self, query_string, sort_by=None, start_offset=0, end_offset=None, + fields='', highlight=False, facets=None, + date_facets=None, query_facets=None, + narrow_queries=None, spelling_query=None, + within=None, dwithin=None, distance_point=None, + models=None, limit_to_registered_models=None, + result_class=None): + + kwargs = super(ElasticsearchSearchBackend, self).build_search_kwargs(query_string, sort_by=sort_by, start_offset=start_offset, end_offset=end_offset, + fields=fields, highlight=highlight, facets=facets, + date_facets=date_facets, query_facets=query_facets, + narrow_queries=narrow_queries, spelling_query=spelling_query, + within=within, dwithin=dwithin, distance_point=distance_point, + models=models, limit_to_registered_models=limit_to_registered_models, + result_class=result_class) + + #TODO : try to make list of field dynamic + #TODO : How to handle multiple + if highlight: + highlight_def = kwargs.get('highlight', {}) + + fields_def = highlight_def.get('fields', {}) + + if models is None or len(models) == 0 or ImageMetadata in models or Fragment in models: + fields_def['tags'] = {} + fields_def['title'] = {} + fields_def['description'] = {} + + kwargs['highlight'] = highlight_def.update({ + 'pre_tags' : [""], + 'post_tags' : [""], + "number_of_fragments" : 0, + 'fields': fields_def + }) + + return kwargs + + def _process_results(self, raw_results, highlight=False, + result_class=None, distance_point=None, + geo_sort=False): + from haystack import connections + results = [] + hits = raw_results.get('hits', {}).get('total', 0) + facets = {} + spelling_suggestion = None + + if result_class is None: + result_class = SearchResult + + if 'facets' in raw_results: + facets = { + 'fields': {}, + 'dates': {}, + 'queries': {}, + } + + for facet_fieldname, facet_info in raw_results['facets'].items(): + if facet_info.get('_type', 'terms') == 'terms': + facets['fields'][facet_fieldname] = [(individual['term'], individual['count']) for individual in facet_info['terms']] + elif facet_info.get('_type', 'terms') == 'date_histogram': + # Elasticsearch provides UTC timestamps with an extra three + # decimals of precision, which datetime barfs on. + facets['dates'][facet_fieldname] = [(datetime.datetime.utcfromtimestamp(individual['time'] / 1000), individual['count']) for individual in facet_info['entries']] + elif facet_info.get('_type', 'terms') == 'query': + facets['queries'][facet_fieldname] = facet_info['count'] + + unified_index = connections[self.connection_alias].get_unified_index() + indexed_models = unified_index.get_indexed_models() + + for raw_result in raw_results.get('hits', {}).get('hits', []): + source = raw_result['_source'] + app_label, model_name = source[DJANGO_CT].split('.') + additional_fields = {} + model = get_model(app_label, model_name) + + if model and model in indexed_models: + for key, value in source.items(): + index = unified_index.get_index(model) + string_key = str(key) + + if string_key in index.fields and hasattr(index.fields[string_key], 'convert'): + additional_fields[string_key] = index.fields[string_key].convert(value) + else: + additional_fields[string_key] = self.conn.to_python(value) + + del(additional_fields[DJANGO_CT]) + del(additional_fields[DJANGO_ID]) + + if 'highlight' in raw_result: + additional_fields['highlighted'] = raw_result['highlight'] + + if distance_point: + additional_fields['_point_of_origin'] = distance_point + + if geo_sort and raw_result.get('sort'): + from haystack.utils.geo import Distance + additional_fields['_distance'] = Distance(km=float(raw_result['sort'][0])) + else: + additional_fields['_distance'] = None + + result = result_class(app_label, model_name, source[DJANGO_ID], raw_result['_score'], **additional_fields) + results.append(result) + else: + hits -= 1 + + return { + 'results': results, + 'hits': hits, + 'facets': facets, + 'spelling_suggestion': spelling_suggestion, + } + + +class ElasticsearchSearchEngine(BaseEngine): + backend = ElasticsearchSearchBackend + query = elasticsearch_backend.ElasticsearchSearchQuery diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/search_indexes/indexes.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/search_indexes/indexes.py Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,45 @@ +# -*- coding: utf-8 -*- +''' +Created on Feb 12, 2013 + +@author: ymh +''' + +from haystack import indexes +from egonomy.models import ImageMetadata +from egonomy.models import Fragment + + +class ImageMetadataIndex(indexes.SearchIndex, indexes.Indexable): + + text = indexes.CharField(document=True, use_template=True) + + id = indexes.CharField(model_attr='id', indexed=False, stored=True) + title = indexes.CharField(model_attr='titre', null=True) + description = indexes.CharField(model_attr='description', null=True) + photograph = indexes.CharField(model_attr='photographe', null=True) + author = indexes.CharField(model_attr='auteur', null=True) + period = indexes.CharField(model_attr='periode', null=True) + technic = indexes.CharField(model_attr='technique', null=True) + site = indexes.CharField(model_attr='site', null=True) + location = indexes.CharField(model_attr='lieu', null=True) + localization = indexes.CharField(model_attr='localisation', null=True) + tags = indexes.CharField(model_attr='mots_cles', null=True) + + def get_model(self): + return ImageMetadata + + +class FragmentIndex(indexes.SearchIndex, indexes.Indexable): + + text = indexes.CharField(document=True, use_template=True) + + id = indexes.IntegerField(model_attr='id', indexed=False, stored=True) + image = indexes.CharField(model_attr='image', indexed=False, stored=True) + author = indexes.CharField(model_attr='author', null=True) + title = indexes.CharField(model_attr='title', null=True) + description = indexes.CharField(model_attr='description', null=True) + tags = indexes.CharField(model_attr='tags', null=True) + + def get_model(self): + return Fragment diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/search_indexes/processor.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/search_indexes/processor.py Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,21 @@ +# -*- coding: utf-8 -*- +''' +Created on Feb 12, 2013 + +@author: ymh +''' + +from egonomy.models import Fragment +from django.db import models +from haystack import signals + +class EgonomySignalProcessor(signals.BaseSignalProcessor): + def setup(self): + # Listen only to the ``User`` model. + models.signals.post_save.connect(self.handle_save, sender=Fragment) + models.signals.post_delete.connect(self.handle_delete, sender=Fragment) + + def teardown(self): + # Disconnect only for the ``User`` model. + models.signals.post_save.disconnect(self.handle_save, sender=Fragment) + models.signals.post_delete.disconnect(self.handle_delete, sender=Fragment) diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/search_indexes/query_parser.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/search_indexes/query_parser.py Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,173 @@ +# -*- coding: utf-8 -*- +''' +Created on Aug 1, 2012 + +@author: ymh +''' + +#TODO: unitest for + +from whoosh.qparser import SimpleParser, FieldsPlugin, OperatorsPlugin, PhrasePlugin, SingleQuotePlugin, GroupPlugin, PrefixPlugin, GtLtPlugin, RangePlugin +from whoosh.query import Term, And, AndMaybe, Or, AndNot, Not, Phrase, Prefix, TermRange +from haystack.query import SQ +from django.conf import settings + +HAYSTACK_DEFAULT_OPERATOR = getattr(settings,'HAYSTACK_DEFAULT_OPERATOR','AND') + +class QueryParser(object): + + + def __init__(self, fieldname): + ''' + Constructor + ''' + self.w_parser = SimpleParser(fieldname, None) + self.w_parser.add_plugin(FieldsPlugin()) + self.w_parser.add_plugin(OperatorsPlugin()) + self.w_parser.add_plugin(PhrasePlugin()) + self.w_parser.add_plugin(SingleQuotePlugin()) + self.w_parser.add_plugin(GroupPlugin()) + self.w_parser.add_plugin(PrefixPlugin()) + self.w_parser.add_plugin(GtLtPlugin()) + self.w_parser.add_plugin(RangePlugin()) + self.query = None + self.current_node_stack = [] + + def parse(self, query): + + self.query = SQ() + self.current_node_stack = [(self.query, HAYSTACK_DEFAULT_OPERATOR)] + + wquery = self.w_parser.parse(query) + + self.visit(wquery) + + if len(self.query) == 1 and isinstance(self.query.children[0], SQ): + return self.query.children[0] + else: + return self.query + + + def visit(self, q): + + if isinstance(q, Term): + current_node, current_connector = self.current_node_stack.pop() + current_node.add(SQ(**{q.fieldname:q.text}), current_connector) + self.current_node_stack.append((current_node,current_connector)) + elif isinstance(q, And): + self._add_compound_query(q, SQ.AND) + elif isinstance(q, AndMaybe): + self._add_andmaybe(q) + elif isinstance(q, Or): + self._add_compound_query(q, SQ.OR) + elif isinstance(q, AndNot): + self._add_andnot(q) + elif isinstance(q, Not): + self._add_not(q) + elif isinstance(q, Phrase): + self._add_phrase(q) + elif isinstance(q, Prefix): + self._add_prefix(q) + elif isinstance(q, TermRange): + self._add_range(q) + + def _add_compound_query(self, q, connector): + + new_node = SQ() + self.current_node_stack.append((new_node, connector)) + for subquery in q.subqueries: + self.visit(subquery) + self.current_node_stack.pop() + + if len(new_node)==1 and isinstance(new_node.children[0], SQ) : + new_node = new_node.children[0] + + current_node, current_connector = self.current_node_stack[-1] + current_node.add(new_node, current_connector) + + + def _add_andnot(self, q): + + new_node = SQ() + self.current_node_stack.append((new_node, SQ.AND)) + self.visit(q.a) + self.visit(Not(q.b)) + self.current_node_stack.pop() + + if len(new_node)==1 and isinstance(new_node.children[0], SQ) : + new_node = new_node.children[0] + + current_node, current_connector = self.current_node_stack[-1] + current_node.add(new_node, current_connector) + + def _add_andmaybe(self, q): + + new_node = SQ() + self.current_node_stack.append((new_node, SQ.AND)) + self.visit(q.a) + self.visit(q.b) + self.current_node_stack.pop() + + if len(new_node)==1 and isinstance(new_node.children[0], SQ) : + new_node = new_node.children[0] + + current_node, current_connector = self.current_node_stack[-1] + current_node.add(new_node, current_connector) + + + def _add_not(self, q): + + new_node = SQ() + self.current_node_stack.append((new_node, SQ.AND)) + self.visit(q.query) + self.current_node_stack.pop() + + if len(new_node)==1 and isinstance(new_node.children[0], SQ) : + new_node = new_node.children[0] + + current_node, current_connector = self.current_node_stack[-1] + current_node.add(~new_node, current_connector) + + def _add_phrase(self, q): + new_node = SQ(**{q.fieldname+"__exact":" ".join(q.words)}) + current_node, current_connector = self.current_node_stack[-1] + current_node.add(new_node, current_connector) + + def _add_prefix(self, q): + new_node = SQ(**{q.fieldname+"__startswith":q.text}) + current_node, current_connector = self.current_node_stack[-1] + current_node.add(new_node, current_connector) + + def _add_range(self, q): + + if q.start is None: + if q.endexcl: + postfix = "__lt" + else: + postfix = "__lte" + new_node = SQ(**{q.fieldname+postfix:self.__convert_nb(q.end)}) + elif q.end is None: + if q.startexcl: + postfix = "__gt" + else: + postfix = "__gte" + new_node = SQ(**{q.fieldname+postfix:self.__convert_nb(q.start)}) + else: + new_node = SQ(**{q.fieldname+"__range":[self.__convert_nb(q.start),self.__convert_nb(q.end)]}) + + current_node, current_connector = self.current_node_stack[-1] + current_node.add(new_node, current_connector) + + def __convert_nb(self, str_nb): + try: + res = int(str_nb) + return res + except ValueError: + try: + res = float(str_nb) + return res + except ValueError: + return str_nb + + + \ No newline at end of file diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/settings.py --- a/src/egonomy/settings.py Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/settings.py Wed Feb 13 10:13:56 2013 +0100 @@ -21,6 +21,14 @@ } } +HAYSTACK_CONNECTIONS = { + 'default': { + 'ENGINE': '', + 'URL': '', + 'INDEX_NAME': '', + }, +} + # Local time zone for this installation. Choices can be found here: # http://en.wikipedia.org/wiki/List_of_tz_zones_by_name # although not all choices may be available on all operating systems. @@ -121,6 +129,7 @@ 'django_extensions', 'south', 'sorl.thumbnail', + 'haystack', 'egonomy', ) @@ -159,6 +168,9 @@ } } + +HAYSTACK_SIGNAL_PROCESSOR = 'egonomy.search_indexes.EgonomySignalProcessor' + from .config import * #@UnusedWildImport if not "SRC_BASE_URL" in locals(): @@ -167,3 +179,5 @@ if not "LOGIN_URL" in locals(): LOGIN_URL = SRC_BASE_URL + 'login/' +if not "IMAGES_PER_PAGE" in locals(): + IMAGES_PER_PAGE = 32 diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/templates/egonomy_base.html --- a/src/egonomy/templates/egonomy_base.html Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/templates/egonomy_base.html Wed Feb 13 10:13:56 2013 +0100 @@ -20,7 +20,7 @@

TagItAll {% trans "by" %} eGonomy

-
+
diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/templates/search/indexes/egonomy/fragment_text.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/templates/search/indexes/egonomy/fragment_text.txt Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,4 @@ +{{ object.title }} +{{ object.description }} +{{ object.tags }} +{{ object.author.name }} \ No newline at end of file diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/templates/search/indexes/egonomy/imagemetadata_text.txt --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/egonomy/templates/search/indexes/egonomy/imagemetadata_text.txt Wed Feb 13 10:13:56 2013 +0100 @@ -0,0 +1,9 @@ +{{ object.titre }} +{{ object.description }} +{{ object.photographe }} +{{ object.auteur }} +{{ object.periode }} +{{ object.site }} +{{ object.lieu }} +{{ object.localisation }} +{{ object.mots_cles }} \ No newline at end of file diff -r 365c73a0e8c1 -r daa526d27044 src/egonomy/views.py --- a/src/egonomy/views.py Mon Feb 11 15:13:19 2013 +0100 +++ b/src/egonomy/views.py Wed Feb 13 10:13:56 2013 +0100 @@ -6,6 +6,9 @@ from models import Image, Fragment from django.db.models.aggregates import Max import logging +from haystack.query import SearchQuerySet +from egonomy.search_indexes import QueryParser +from egonomy.models import ImageMetadata logger = logging.getLogger(__name__) @@ -94,9 +97,25 @@ # Get the cur_page_nb number parameter if possible cur_page_nb = request.GET.get("page") or 1 cur_page_nb = int(cur_page_nb) + + search = None + if "search" in request.GET: + search = request.GET["search"] + field = "all" + if "field" in request.GET: + field = request.GET["field"] + + img_list = Image.objects.order_by('pk').select_related('info', 'metadata') + if search: + if not field or field == 'all': + field = 'text' + qp = QueryParser(field) + res = SearchQuerySet().filter(qp.parse(search)).models(ImageMetadata) + img_list = Image.objects.filter(id__in=[r.pk for r in res]) + else: + img_list = img_list.all() - img_list = Image.objects.all().order_by('pk').select_related('info', 'metadata') - nb = 32 + nb = getattr(settings,"IMAGES_PER_PAGE", 32) paginator = Paginator(img_list, nb) try: results = paginator.page(cur_page_nb) @@ -115,7 +134,7 @@ cur_page_nb = int(cur_page_nb) frg_list = Fragment.objects.all().order_by('pk').select_related('image', 'image__info', 'image__metadata','author') - nb = 32 + nb = getattr(settings,"IMAGES_PER_PAGE", 32) paginator = Paginator(frg_list, nb) try: results = paginator.page(cur_page_nb) diff -r 365c73a0e8c1 -r daa526d27044 virtualenv/res/lib/lib_create_env.py --- a/virtualenv/res/lib/lib_create_env.py Mon Feb 11 15:13:19 2013 +0100 +++ b/virtualenv/res/lib/lib_create_env.py Wed Feb 13 10:13:56 2013 +0100 @@ -28,7 +28,7 @@ 'PARAMIKO': {'setup': 'paramiko', 'url':'https://github.com/paramiko/paramiko/archive/v1.9.0.tar.gz', 'local':'paramiko-1.9.0.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'FABRIC': {'setup': 'fabric', 'url':'https://github.com/fabric/fabric/tarball/1.5.1', 'local':'fabric-1.5.1.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, 'MERCURIAL': {'setup': 'mercurial', 'url':'http://mercurial.selenic.com/release/mercurial-2.2.3.tar.gz', 'local':'mercurial-2.2.3.tar.gz', 'install': {'method': 'pip', 'option_str': None, 'dict_extra_env': None}}, - 'HAYSTACK': {'setup': 'django-haystack', 'url': 'https://github.com/toastdriven/django-haystack/tarball/master', 'local': 'django-haystack-v2.0.0.tar.gz', 'install':{'method':'pip', 'option_str': None, 'dict_extra_env': None}}, + 'HAYSTACK': {'setup': 'django-haystack', 'url': 'https://github.com/toastdriven/django-haystack/tarball/master', 'local': 'django-haystack-v2.0.0-beta.tar.gz', 'install':{'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'REQUESTS': {'setup': 'requests', 'url':'https://github.com/kennethreitz/requests/archive/v1.1.0.tar.gz', 'local':'requests-1.1.0.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'PYELASTICSEARCH': {'setup': 'pyelasticsearch', 'url':'https://github.com/rhec/pyelasticsearch/archive/0.3.tar.gz', 'local':'pyelasticsearch-0.3.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, 'WHOOSH': {'setup': 'whoosh', 'url':'https://bitbucket.org/mchaput/whoosh/get/tip.tar.gz', 'local':'whoosh-2.5.tar.gz', 'install' : {'method':'pip', 'option_str': None, 'dict_extra_env': None}}, diff -r 365c73a0e8c1 -r daa526d27044 virtualenv/res/src/django-haystack-V2.0.0-beta.tar.gz Binary file virtualenv/res/src/django-haystack-V2.0.0-beta.tar.gz has changed diff -r 365c73a0e8c1 -r daa526d27044 virtualenv/res/src/django-haystack-v2.0.0.tar.gz Binary file virtualenv/res/src/django-haystack-v2.0.0.tar.gz has changed