]> git.parisson.com Git - telemeta.git/commitdiff
add advanced search
authorolivier <>
Thu, 6 Mar 2008 19:16:54 +0000 (19:16 +0000)
committerolivier <>
Thu, 6 Mar 2008 19:16:54 +0000 (19:16 +0000)
telemeta/htdocs/css/telemeta.css
telemeta/models.py
telemeta/templates/base.html
telemeta/templates/inc/collection_list.html
telemeta/templates/inc/mediaitem_list.html
telemeta/templatetags/telemeta_utils.py
telemeta/urls.py
telemeta/web/base.py

index ce49f135abffdb9b9d82a9a20baba66580e5a6c8..89094c8c481dce6388c0636dcf911f10ff09e483 100644 (file)
@@ -30,7 +30,8 @@ a img { border: none; }
 #submenu { clear: right; float: right; padding-top: 1em; }\r
 #submenu a { color: #000066; }\r
 \r
-#quick_search { position: absolute; top: 2em; right: 1em; }\r
+#quick_search { position: absolute; top: 2em; right: 1em; text-align: right;}\r
+#quick_search a { font-size: 80%; }    \r
 #quick_search input {\r
     vertical-align: middle;\r
     font-size: 90%;\r
index bc144ebf33b05df0f8b4032d6c2e572a5ad13077..c97ca7f94ae72c40c81d9af12cf10043d2275030 100644 (file)
@@ -9,6 +9,7 @@
 
 from django.db.models import Manager, Model, Q, CharField, FileField, \
     TextField, DecimalField, ForeignKey, DateField
+from django.db.models.query import QuerySet
 from django.core.exceptions import ObjectDoesNotExist
 from django.core import validators
 from django.conf import settings
@@ -82,13 +83,25 @@ class PublishingStatus(Model):
     class Meta:
         ordering = ['value']
         verbose_name_plural = "Publishing status"
-        
-class MediaCollectionManager(Manager):
-    "Manage collection queries"
+
+class CoreQuerySet(QuerySet):
+    "Base class for all query sets"
+
+    def none(self): # redundant with none() in recent Django svn
+        "Return an empty result set"
+        return self.extra(where = ["0 = 1"])
+
+class CoreManager(Manager):
+    "Base class for all models managers"
+
+    def none(self, *args, **kwargs):
+        return self.get_query_set().none(*args, **kwargs)
+
+class MediaCollectionQuerySet(CoreQuerySet):
 
     def quick_search(self, pattern):
         "Perform a quick search on id, title and creator name"
-        return super(MediaCollectionManager, self).get_query_set().filter(
+        return self.filter(
             Q(id__icontains=pattern) |
             Q(title__icontains=pattern) |
             Q(creator__icontains=pattern)
@@ -96,22 +109,58 @@ class MediaCollectionManager(Manager):
 
     def by_country(self, country):
         "Find collections by country"
-        qs = super(MediaCollectionManager, self).get_query_set()
-        return qs.extra(where = ["id IN (SELECT collection_id "
+        return self.extra(where = ["id IN (SELECT collection_id "
             "FROM telemeta_item WHERE etat = %s)"],
             params=[country]);
+    
+    def by_continent(self, continent):
+        "Find collections by continent"
+        return self.extra(where = ["id IN (SELECT collection_id "
+            "FROM telemeta_item WHERE continent = %s)"],
+            params=[continent]);
+
+    def by_recording_date(self, pattern):
+        return self.filter(annee_enr__icontains=pattern)
+
+    def by_publish_date(self, pattern):
+        return self.filter(date_published__icontains=pattern) 
+
+class MediaCollectionManager(CoreManager):
+    "Manage collection queries"
+
+    def get_query_set(self):
+        return MediaCollectionQuerySet(self.model)
 
-    def stat_continents(self):      
+    def quick_search(self, *args, **kwargs):
+        return self.get_query_set().quick_search(*args, **kwargs)
+
+    def by_country(self, *args, **kwargs):
+        return self.get_query_set().by_country(*args, **kwargs)
+
+    def by_continent(self, *args, **kwargs):
+        return self.get_query_set().by_continent(*args, **kwargs)
+
+    def by_recording_date(self, *args, **kwargs):
+        return self.get_query_set().by_recording_date(*args, **kwargs)
+
+    def by_publish_date(self, *args, **kwargs):
+        return self.get_query_set().by_publish_date(*args, **kwargs)
+
+    def stat_continents(self, order_by='num'):      
         "Return the number of collections by continents and countries as a tree"
         from django.db import connection
         cursor = connection.cursor()
+        if order_by == 'num':
+            order_by = 'items_num DESC'
+        else:
+            order_by = 'etat'
         cursor.execute("SELECT continent, etat, count(*) AS items_num "
             "FROM telemeta_collection INNER JOIN telemeta_item "
             "ON telemeta_collection.id = telemeta_item.collection_id "
             "WHERE (continent IN "
             "  ('EUROPE', 'OCEANIE', 'ASIE', 'AMERIQUE', 'AFRIQUE')) "
             "AND etat <> '' "
-            "GROUP BY etat ORDER BY continent, items_num desc;")
+            "GROUP BY etat ORDER BY continent, " + order_by)
         result_set = cursor.fetchall()
         stat = {}
         for continent, country, count in result_set:
@@ -125,6 +174,31 @@ class MediaCollectionManager(Manager):
         ordered = [{'name': k, 'countries': stat[k]} for k in keys]
         return ordered
 
+    def list_countries(self):
+        "Return a 2D list of all countries with continents"
+
+        from django.db import connection
+        cursor = connection.cursor()
+
+        cursor.execute("SELECT continent, etat FROM telemeta_item "
+            "GROUP BY continent, etat ORDER BY REPLACE(etat, '\"', '')");
+        return cursor.fetchall()
+
+    def list_continents(self):
+        "Return a list of all continents"
+        
+        from django.db import connection
+        cursor = connection.cursor()
+
+        cursor.execute("SELECT DISTINCT(continent) FROM telemeta_item ORDER BY continent")
+        result_set = cursor.fetchall()
+        result = []
+        for a, in result_set:
+            if a != '' and a != 'N': # CREM fix
+                result.append(a)
+        
+        return result
+
 class MediaCollection(Model, MediaCore):
     "Group related media items"
 
@@ -216,22 +290,55 @@ class MediaCollection(Model, MediaCore):
     class Admin:
         pass
 
-class MediaItemManager(Manager):
-    "Manage media items queries"
-
+class MediaItemQuerySet(CoreQuerySet):
+    
     def quick_search(self, pattern):
         "Perform a quick search on id and title"
-        return super(MediaItemManager, self).get_query_set().filter(
+        return self.filter(
             Q(id__icontains=pattern) |
             Q(_title__icontains=pattern) 
         )
 
     def without_collection(self):        
         "Find items which do not belong to any collection"
-        qs = super(MediaItemManager, self).get_query_set()
-        return qs.extra(
+        return self.extra(
             where = ["collection_id NOT IN (SELECT id FROM telemeta_collection)"]);
 
+    def by_recording_date(self, pattern):
+        return self.filter(Q(dates_enregistr__icontains=pattern) 
+            | Q(annee_enreg__icontains=pattern))
+
+class MediaItemManager(CoreManager):
+    "Manage media items queries"
+
+    def get_query_set(self):
+        return MediaItemQuerySet(self.model)
+
+    def quick_search(self, *args, **kwargs):
+        return self.get_query_set().quick_search(*args, **kwargs)
+
+    def without_collection(self, *args, **kwargs):
+        return self.get_query_set().without_collection(*args, **kwargs)
+
+    def by_recording_date(self, *args, **kwargs):
+        return self.get_query_set().by_recording_date(*args, **kwargs)
+
+    def list_ethnic_groups(self):
+        "Return a list of all ethnic groups"
+        
+        from django.db import connection
+        cursor = connection.cursor()
+
+        cursor.execute("SELECT DISTINCT(ethnie_grsocial) FROM telemeta_item "
+            "ORDER BY REPLACE(ethnie_grsocial, '\\'', '')")
+        result_set = cursor.fetchall()
+        result = []
+        for a, in result_set:
+            if a != '/' and a != '': # CREM fix
+                result.append(a)
+        
+        return result
+
 class MediaItem(Model, MediaCore):
     "Describe an item with metadata" 
 
index fe6893668347da3410438090f1d08a1d85e1f55b..01cdb0d60bb5b8e94527ed336351d9fc5033030e 100644 (file)
 </div>
 
 <div id="quick_search">
-<form action="{% url telemeta-quicksearch %}" method="GET">
+<form action="{% url telemeta-search %}" method="GET">
 <input id="quick_search_pattern" name="pattern" />
 <input type="submit" value="Search" />
 </form>        
+<a href="{% url telemeta-search-criteria %}">Advanced search</a>
 </div>
 
 <div id="menu" class="nav">
index 5a41864d41b3e65b0427cce143e4f785b0ec8ff8..64a5cc3f187454b10bc3cb5722548436248a4d3c 100644 (file)
@@ -11,6 +11,7 @@
         <li><a href="{% url telemeta-collection-detail p.id|urlencode %}">{{ p.title }}</a>
             </li>
     {% endfor %}
+    {% if more_collections %} <li>[...]</li> {% endif %}
     </ul>
 {% else %}
     <p>No collection</p>
index 08248e4368b814f9c8b315380a65579c76e85f78..699ba3c9bd73767ba2eff75b549b611470be1dea 100644 (file)
@@ -10,6 +10,7 @@
     {% for p in items %}
         <li><a href="{% url telemeta-item-detail p.id|urlencode %}">{{ p.title }}</a></li>
     {% endfor %}
+    {% if more_items %} <li>[...]</li> {% endif %}
     </ul>
 {% else %}
     <p>No item</p>
index 6866c5f9732e8d5bc598469b507b30e4cf6924db..f20186b98544e93b9193ab5ba7c0ed8be5197fbc 100644 (file)
@@ -41,4 +41,23 @@ def telemeta_url(parser, token):
     "Get Telemeta project homepage URL"
     return TelemetaUrlNode()
 
+_js_escapes = (
+    ('\\', '\\\\'),
+    ('"', '\\"'),
+    ("'", "\\'"),
+    ('\n', '\\n'),
+    ('\r', '\\r'),
+    ('\b', '\\b'),
+    ('\f', '\\f'),
+    ('\t', '\\t'),
+    ('\v', '\\v'),
+    ('</', '<\\/'),
+)
+@register.filter
+def escapejs(value):
+    """Backslash-escapes characters for use in JavaScript strings."""
+    for bad, good in _js_escapes:
+        value = value.replace(bad, good)
+    return value
+
 
index 8923ab261e2c8ef6d18fb8b09684a5401260fb10..4da2f93809133dcca46e423ac2c2371f4400cc3b 100644 (file)
@@ -81,7 +81,8 @@ urlpatterns = patterns('',
         name="telemeta-collection-m3u"),
 
     # search
-    url(r'^search/$', web_view.quick_search, name="telemeta-quicksearch"),
+    url(r'^search/$', web_view.search, name="telemeta-search"),
+    url(r'^search/criteria/$', web_view.edit_search, name="telemeta-search-criteria"),
 
     # administration        
     url(r'^admin/$', web_view.admin_index, name="telemeta-admin"),        
@@ -112,6 +113,7 @@ urlpatterns = patterns('',
     url('geo/(?P<continent>[A-Za-z]+)/(?P<country>[-A-Za-z0-9%;.,"& \']+)/$', 
         web_view.list_country_collections, 
         name="telemeta-geo-country-collections"),
+    url(r'dynjs/continents.js$', web_view.get_continents_js, name="telemeta-continents-js"),
 
     # CSS+Images (FIXME: for developement only)
     url(r'css/(?P<path>.*)$', 'django.views.static.serve', 
index 7faa4f4847075abb1dd490734579f27f1cc5ccad..eb358d82cb392ef8b93988eb22f4e17a093913b9 100644 (file)
@@ -101,14 +101,55 @@ class WebView(Component):
         response['Content-Disposition'] = 'attachment'
         return response
 
-    def quick_search(self, request):
-        """Perform a simple search through collections and items core metadata"""
-        pattern = request.REQUEST["pattern"]
-        collections = MediaCollection.objects.quick_search(pattern)
-        items = MediaItem.objects.quick_search(pattern)
+    def edit_search(self, request):
+        continents = MediaCollection.objects.list_continents()
+        countries = MediaCollection.objects.list_countries()
+        ethnic_groups = MediaItem.objects.list_ethnic_groups()
+        return render_to_response('search_criteria.html', 
+            {'continents': continents, 'countries': countries, 
+            'ethnic_groups': ethnic_groups})
+
+    def search(self, request):
+        """Perform a search through collections and items metadata"""
+        collections = MediaCollection.objects
+        items = MediaItem.objects
+        input = request.REQUEST
+
+        if input.has_key('pattern') and input['pattern']:
+            collections = collections.quick_search(input['pattern'])
+            items = items.quick_search(input['pattern'])
+
+        if input.has_key('country') and input['country']:
+            collections = collections.by_country(input['country'])
+            items = items.filter(etat = input['country'])
+        elif input.has_key('continent') and input['continent']:
+            collections = collections.by_continent(input['continent'])
+            items = items.filter(continent = input['continent'])
+      
+        if (input.has_key('ethnic_group') and input['ethnic_group']):
+            collections = collections.none()
+            items = items.filter(ethnie_grsocial = input['ethnic_group'])
+
+        if (input.has_key('creator') and input['creator']):
+            collections = collections.filter(creator__icontains=input['creator'])
+            items = items.filter(auteur__icontains=input['creator'])
+
+        if (input.has_key('creator') and input['creator']):
+            collections = collections.filter(creator__icontains=input['creator'])
+            items = items.filter(auteur__icontains=input['creator'])
+
+        if (input.has_key('rec_date') and input['rec_date']):
+            collections = collections.by_recording_date(input['rec_date'])
+            items = items.by_recording_date(input['rec_date'])
+
+        if (input.has_key('pub_date') and input['pub_date']):
+            collections = collections.by_publish_date(input['pub_date'])
+            items = items.none()
+
         return render_to_response('search_results.html', 
-                    {'pattern': pattern, 'collections': collections, 
-                     'items': items})
+                    {'criteria': input, 
+                    'collections': collections[:50], 'more_collections': collections.count() > 50,
+                     'items': items[:50], 'more_items': items.count() > 50})
 
     def __get_enumerations_list(self):
         from django.db.models import get_models
@@ -124,6 +165,13 @@ class WebView(Component):
     def __get_admin_context_vars(self):
         return {"enumerations": self.__get_enumerations_list()}
 
+    def __continents_to_countries(self, tree):
+        countries = []
+        for continent in tree:
+            countries += continent['countries']
+        #countries.sort()
+        return countries
+
     def admin_index(self, request):
         return render_to_response('admin.html', self. __get_admin_context_vars())
 
@@ -223,6 +271,11 @@ class WebView(Component):
         return render_to_response('geo_continents.html', 
                     {'continents': continents })
 
+    def get_continents_js(self, request):
+        countries = MediaCollection.objects.list_countries()
+        return render_to_response('geo_continents.js', 
+                    {'countries': countries})
+
     def list_countries(self, request, continent):                    
         continents = MediaCollection.objects.stat_continents()
         for c in continents: