Retour à la situation pré-Sphinx
authorEric Mc Sween <eric.mcsween@gmail.com>
Thu, 2 Dec 2010 20:36:18 +0000 (15:36 -0500)
committerEric Mc Sween <eric.mcsween@gmail.com>
Thu, 2 Dec 2010 20:36:18 +0000 (15:36 -0500)
21 files changed:
auf_savoirs_en_partage/chercheurs/admin.py
auf_savoirs_en_partage/chercheurs/forms.py
auf_savoirs_en_partage/chercheurs/models.py
auf_savoirs_en_partage/development.py
auf_savoirs_en_partage/savoirs/admin.py
auf_savoirs_en_partage/savoirs/forms.py
auf_savoirs_en_partage/savoirs/lib/recherche.py
auf_savoirs_en_partage/savoirs/models.py
auf_savoirs_en_partage/savoirs/rss.py
auf_savoirs_en_partage/savoirs/templatetags/sep.py
auf_savoirs_en_partage/savoirs/views.py
auf_savoirs_en_partage/scripts/sphinx.conf.py.in [deleted file]
auf_savoirs_en_partage/settings.py
auf_savoirs_en_partage/sitotheque/forms.py
auf_savoirs_en_partage/sitotheque/models.py
auf_savoirs_en_partage/sitotheque/views.py
auf_savoirs_en_partage/templates/savoirs/actualite_resultat.html
auf_savoirs_en_partage/templates/savoirs/evenement_resultat.html
auf_savoirs_en_partage/templates/savoirs/ressource_resultat.html
auf_savoirs_en_partage/templates/sites/resultat.html
buildout.cfg

index e0b37ba..158aac2 100644 (file)
@@ -12,9 +12,6 @@ class ChercheurAdmin(admin.ModelAdmin):
     actions = ('remove_from_group',)
     search_fields = ('personne__nom', 'personne__prenom')
 
-    def queryset(self, request):
-        return Chercheur.all_objects.get_query_set()
-
     def remove_from_group(self, request, queryset):
         groupe_id = request.GET.get('groupes__id__exact')
         chercheur_ids = queryset.values_list('id', flat=True)
index 0f5d0d2..7ac665d 100644 (file)
@@ -283,39 +283,40 @@ class RepertoireSearchForm (forms.Form):
             pays.queryset = pays.queryset.filter(region=region)
 
     def get_query_set(self):
-        chercheurs = Chercheur.objects
+        qs = Chercheur.objects.all()
         if self.is_valid():
-            q = self.cleaned_data["q"]
-            if q:
-                chercheurs = chercheurs.search(q)
             nom = self.cleaned_data['nom']
             if nom:
-                chercheurs = chercheurs.add_to_query('@(nom,prenom) ' + nom)
+                qs = qs.search_nom(nom)
+            domaine = self.cleaned_data["domaine"]
+            if domaine:
+                qs = qs.filter(groupes=domaine)
             groupe_recherche = self.cleaned_data['groupe_recherche']
             if groupe_recherche:
-                chercheurs = chercheurs.add_to_query('@groupe_recherche ' + groupe_recherche)
-            discipline = self.cleaned_data['discipline']
-            if discipline:
-                chercheurs = chercheurs.filter_discipline(discipline)
-            region = self.cleaned_data['region']
-            if region:
-                chercheurs = chercheurs.filter_region(region)
+                for word in groupe_recherche.split():
+                    qs = qs.filter(groupe_recherche__icontains=word)
+            q = self.cleaned_data["q"]
+            if q:
+                qs = qs.search(q)
             statut = self.cleaned_data["statut"]
             if statut:
                 if statut == "expert":
-                    chercheurs = chercheurs.filter_expert()
+                    qs = qs.exclude(expertises=None)
                 else:
-                    chercheurs = chercheurs.filter_statut(statut)
-            domaine = self.cleaned_data["domaine"]
-            if domaine:
-                chercheurs = chercheurs.filter_groupe(domaine)
+                    qs = qs.filter(statut=statut)
+            discipline = self.cleaned_data['discipline']
+            if discipline:
+                qs = qs.filter_discipline(discipline)
+            region = self.cleaned_data['region']
+            if region:
+                qs = qs.filter_region(region)
             pays = self.cleaned_data["pays"]
             if pays:
-                chercheurs = chercheurs.filter_pays(pays)
+                qs = qs.filter(Q(etablissement__pays=pays) | Q(etablissement_autre_pays=pays))
             nord_sud = self.cleaned_data['nord_sud']
             if nord_sud:
-                chercheurs = chercheurs.filter_nord_sud(nord_sud)
-        return chercheurs.all()
+                qs = qs.filter(Q(etablissement__pays__nord_sud=nord_sud) | Q(etablissement_autre_pays__nord_sud=nord_sud))
+        return qs
     
 class SendPasswordForm(forms.Form):
     email = forms.EmailField(required=True, label="Adresse électronique")
index 5e15c5a..c4063d4 100644 (file)
@@ -1,11 +1,11 @@
 # -*- encoding: utf-8 -*-
 import hashlib
-from datamaster_modeles.models import *
 from django.db import models
 from django.db.models import Q
 from django.utils.encoding import smart_str
-from djangosphinx.models import SphinxSearch
-from savoirs.models import Discipline, SEPManager, SEPSphinxQuerySet, SEPQuerySet
+from datamaster_modeles.models import *
+#from auf_references_modeles.models import Thematique
+from savoirs.models import Discipline, RandomQuerySetMixin
 
 GENRE_CHOICES = (('m', 'Homme'), ('f', 'Femme'))
 class Personne(models.Model):
@@ -45,80 +45,102 @@ class Utilisateur(Personne):
         return hashlib.md5(smart_str(clear_password)).hexdigest()
 
     def get_new_password_code(self):
-        return hashlib.md5(smart_str(u.courriel+u.encrypted_password)).hexdigest()[0:6]
-
-class ChercheurQuerySet(SEPQuerySet):
-
-    def filter_groupe(self, groupe):
-        return self.filter(groupes=groupe)
-
-    def filter_pays(self, pays):
-        return self.filter(Q(etablissement__pays=pays) | Q(etablissement_autre_pays=pays))
-
-    def filter_region(self, region):
-        return self.filter(Q(etablissement__pays__region=region) | Q(etablissement_autre_pays__region=region))
-
-    def filter_nord_sud(self, nord_sud):
-        return self.filter(Q(etablissement__pays__nord_sud=nord_sud) | Q(etablissement_autre_pays__nord_sud=nord_sud))
-
-    def filter_statut(self, statut):
-        return self.filter(statut=statut)
-
-    def filter_expert(self):
-        return self.exclude(expertises=None)
-
-class ChercheurSphinxQuerySet(SEPSphinxQuerySet):
-
-    def __init__(self, model=None):
-        return SEPSphinxQuerySet.__init__(self, model=model, index='savoirsenpartage_chercheurs',
-                                          weights=dict(nom=2, prenom=2))
+        return hashlib.md5(smart_str(self.courriel + self.encrypted_password)).hexdigest()[0:6]
 
-    def filter_region(self, region):
-        return self.filter(region_id=region.id)
-
-    def filter_groupe(self, groupe):
-        return self.filter(groupe_ids=groupe.id)
-
-    def filter_pays(self, pays):
-        return self.filter(pays_id=pays.id)
-
-    NORD_SUD_CODES = {'Nord': 1, 'Sud': 2}
-    def filter_nord_sud(self, nord_sud):
-        return self.filter(nord_sud=self.NORD_SUD_CODES[nord_sud])
-
-    STATUT_CODES = {'enseignant': 1, 'etudiant': 2, 'independant': 3}
-    def filter_statut(self, statut):
-        return self.filter(statut=self.STATUT_CODES[statut])
-
-    def filter_expert(self):
-        return self.filter(expert=1)
-
-class ChercheurManager(SEPManager):
+class ChercheurManager(models.Manager):
 
     def get_query_set(self):
         return ChercheurQuerySet(self.model)
 
-    def get_sphinx_query_set(self):
-        return ChercheurSphinxQuerySet(self.model).order_by('-date_modification')
+    def search(self, text):
+        return self.get_query_set().search(text)
+
+    def search_nom(self, nom):
+        return self.get_query_set().search_nom(nom)
 
     def filter_region(self, region):
-        """Le filtrage de chercheurs par région n'est pas une recherche texte."""
         return self.get_query_set().filter_region(region)
 
-    def filter_groupe(self, groupe):
-        return self.get_query_set().filter_groupe(groupe)
-
-    def filter_pays(self, pays):
-        return self.get_query_set().filter_pays(pays)
+    def filter_discipline(self, discipline):
+        return self.get_query_set().filter_discipline(discipline)
+
+class ChercheurQuerySet(models.query.QuerySet, RandomQuerySetMixin):
+
+    def search(self, text):
+        q = None
+        for word in text.split():
+            matching_pays = list(Pays.objects.filter(Q(nom__icontains=word) | Q(region__nom__icontains=word)).values_list('pk', flat=True))
+            matching_etablissements = list(Etablissement.objects.filter(Q(nom__icontains=word) | Q(pays__in=matching_pays)).values_list('pk', flat=True))
+            matching_publications = list(Publication.objects.filter(titre__icontains=word).values_list('pk', flat=True))
+            matching_groupes = list(Groupe.objects.filter(nom__icontains=word).values_list('pk', flat=True))
+            matching_disciplines = list(Discipline.objects.filter(nom__icontains=word).values_list('pk', flat=True))
+            part = (Q(personne__nom__icontains=word) |
+                    Q(personne__prenom__icontains=word) |
+                    Q(theme_recherche__icontains=word) |
+                    Q(etablissement__in=matching_etablissements) |
+                    Q(etablissement_autre_nom__icontains=word) |
+                    Q(etablissement_autre_pays__in=matching_pays) |
+                    Q(discipline__in=matching_disciplines) |
+                    Q(groupe_recherche__icontains=word) |
+                    Q(publication1__in=matching_publications) |
+                    Q(publication2__in=matching_publications) |
+                    Q(publication3__in=matching_publications) |
+                    Q(publication4__in=matching_publications) |
+                    Q(these__in=matching_publications) |
+                    Q(groupes__in=matching_groupes) |
+                    Q(expertises__nom__icontains=word) |
+                    Q(mots_cles__icontains=word) |
+                    Q(membre_association_francophone_details__icontains=word) |
+                    Q(membre_reseau_institutionnel_details__icontains=word)
+                   )
+            if q is None:
+                q = part
+            else:
+                q = q & part
+        return self.filter(q).distinct() if q is not None else self
+
+    def search_nom(self, nom):
+        q = None
+        for word in nom.split():
+            part = Q(personne__nom__icontains=word) | Q(personne__prenom__icontains=word)
+            if q is None:
+                q = part
+            else:
+                q = q & part
+        return self.filter(q) if q is not None else self
+
+    def filter_discipline(self, discipline):
+        """Ne conserve que les chercheurs dans la discipline donnée.
+           
+        Si ``disicipline`` est None, ce filtre n'a aucun effet."""
+        if discipline is None:
+            return self
+        if not isinstance(discipline, Discipline):
+            discipline = Discipline.objects.get(pk=discipline)
+        return self.filter(Q(discipline=discipline) |
+                           Q(theme_recherche__icontains=discipline.nom) |
+                           Q(groupe_recherche__icontains=discipline.nom) |
+                           Q(publication1__titre__icontains=discipline.nom) |
+                           Q(publication2__titre__icontains=discipline.nom) |
+                           Q(publication3__titre__icontains=discipline.nom) |
+                           Q(publication4__titre__icontains=discipline.nom) |
+                           Q(these__titre__icontains=discipline.nom) |
+                           Q(groupes__nom__icontains=discipline.nom) |
+                           Q(expertises__nom__icontains=discipline.nom) |
+                           Q(mots_cles__icontains=discipline.nom) |
+                           Q(membre_instance_auf_details__icontains=discipline.nom) |
+                           Q(membre_association_francophone_details__icontains=discipline.nom) |
+                           Q(expert_oif_details__icontains=discipline.nom) |
+                           Q(membre_reseau_institutionnel_details__icontains=discipline.nom)).distinct()
 
-    def filter_nord_sud(self, nord_sud):
-        return self.get_query_set().filter_nord_sud(nord_sud)
-
-    def filter_statut(self, statut):
-        return self.get_query_set().filter_statut(statut)
-
-    def filter_expert(self):
-        return self.get_query_set().filter_expert()
+    def filter_region(self, region):
+        """Ne conserve que les évènements dans la région donnée.
+           
+        Si ``region`` est None, ce filtre n'a aucun effet."""
+        if region is None:
+            return self
+        return self.filter(Q(etablissement__pays__region=region) |
+                           Q(etablissement_autre_pays__region=region))
 
 STATUT_CHOICES = (('enseignant', 'Enseignant-chercheur dans un établissement'), ('etudiant', 'Étudiant-chercheur doctorant'), ('independant', 'Chercheur indépendant docteur'))
 class Chercheur(models.Model):
@@ -201,7 +223,6 @@ class Chercheur(models.Model):
     
     # Manager
     objects = ChercheurManager()
-    all_objects = models.Manager()
 
     def __unicode__(self):
         return u"%s %s" % (self.personne.nom.upper(), self.personne.prenom.title())
index d5eb751..ce669b3 100644 (file)
@@ -8,7 +8,7 @@ INTERNAL_IPS = ('127.0.0.1',)
 
 # MIDDLEWARE_CLASSES += ('debug_toolbar.middleware.DebugToolbarMiddleware',)
 # INSTALLED_APPS += ('debug_toolbar',)
-# DEBUG_TOOLBAR_CONFIG = dict(INTERCEPT_REDIRECTS=True)
+# DEBUG_TOOLBAR_CONFIG = dict(INTERCEPT_REDIRECTS=False)
 
 # Profiling
 
index 10dae3b..345a2e6 100644 (file)
@@ -1,10 +1,8 @@
 # -*- encoding: utf-8 -*-
-import operator
 import re
+
 from django.core.urlresolvers import reverse as url
 from django.db import models
-from django.db.models import Q
-from django.db.models.query import QuerySet
 from django.contrib import admin
 from django.contrib.auth.admin import UserAdmin
 from django.contrib.auth.models import User
@@ -13,8 +11,9 @@ from django.utils.safestring import mark_safe
 from django.utils.translation import ugettext as _
 from django.utils.encoding import smart_unicode, iri_to_uri
 from django.http import HttpResponseRedirect
+
+from models import SourceActualite, Actualite, Discipline, Evenement, Record, ListSet, HarvestLog, Profile
 from savoirs.globals import META
-from savoirs.models import SourceActualite, Actualite, Discipline, Evenement, Record, ListSet, HarvestLog, Profile
 
 admin.site.register(SourceActualite)
 
@@ -83,41 +82,6 @@ class ReadOnlyAdminFields(object):
                     form.base_fields[field_name].required = False
         return form
 
-class RecordAdminQuerySet(QuerySet):
-
-    def filter(self, *args, **kwargs):
-        """Gère des filtres supplémentaires pour l'admin.
-           
-        C'est la seule façon que j'ai trouvée de contourner les mécanismes
-        de recherche de l'admin."""
-        search = kwargs.pop('admin_search', None)
-        search_titre = kwargs.pop('admin_search_titre', None)
-        search_sujet = kwargs.pop('admin_search_sujet', None)
-        search_description = kwargs.pop('admin_search_description', None)
-        search_auteur = kwargs.pop('admin_search_auteur', None)
-
-        if search:
-            qs = self
-            search_all = not (search_titre or search_description or search_sujet or search_auteur)
-            fields = []
-            if search_titre or search_all:
-                fields += ['title', 'alt_title']
-            if search_description or search_all:
-                fields += ['description', 'abstract']
-            if search_sujet or search_all:
-                fields += ['subject']
-            if search_auteur or search_all:
-                fields += ['creator', 'contributor']
-
-            for bit in search.split():
-                or_queries = [Q(**{field + '__icontains': bit}) for field in fields]
-                qs = qs.filter(reduce(operator.or_, or_queries))
-
-            if args or kwargs:
-                qs = super(RecordAdminQuerySet, qs).filter(*args, **kwargs)
-            return qs
-        else:
-            return super(RecordAdminQuerySet, self).filter(*args, **kwargs)
 
 class RecordAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
     fields = ['server', 'title', 'creator', 'description', 'modified',
@@ -144,8 +108,7 @@ class RecordAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
         self.readonly_fields.append('listsets')
         super(RecordAdmin, self).__init__(*args, **kwargs) 
 
-    def queryset(self, request):
-        return RecordAdminQuerySet(Record)
+    # Recherche par mots-clés
 
     # Présentation de l'information
     
@@ -189,6 +152,7 @@ class RecordAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
         selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
         return HttpResponseRedirect(url('assigner_disciplines', kwargs=dict(app_name='savoirs', model_name='record')) + '?ids=' + ','.join(selected))
     assigner_disciplines.short_description = u'Assigner des disciplines'
+
 admin.site.register(Record, RecordAdmin)
 
 class ListSetAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
@@ -225,9 +189,6 @@ class ActualiteAdmin(admin.ModelAdmin):
     list_display = ('titre', 'source', 'date', 'visible')
     actions = ['rendre_visible', 'rendre_invisible', 'assigner_regions', 'assigner_disciplines']
 
-    def queryset(self, request):
-        return Actualite.all_objects.get_query_set()
-
     # actions
     def rendre_visible(self, request, queryset):
         selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
@@ -274,9 +235,6 @@ class EvenementAdmin(admin.ModelAdmin):
               'description', 'contact', 'url', 'approuve']
     actions = ['assigner_regions', 'assigner_disciplines']
 
-    def queryset(self, request):
-        return Evenement.all_objects.get_query_set()
-
     def assigner_regions(self, request, queryset):
         selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
         return HttpResponseRedirect(url('assigner_regions', kwargs=dict(app_name='savoirs', model_name='evenement')) + '?ids=' + ','.join(selected))
index 8d445d4..6620a1d 100644 (file)
@@ -42,30 +42,37 @@ class RecordSearchForm(forms.Form):
     def get_query_set(self):
         """Retourne l'ensemble des ressources qui correspondent aux valeurs
            entrées dans le formulaire."""
-        records = Record.objects
+        records = Record.objects.validated()
         if self.is_valid():
-            q = self.cleaned_data['q']
-            if q:
-                records = records.search(q)
+            query = self.cleaned_data['q']
+            if query:
+                records = records.search(query)
             auteur = self.cleaned_data['auteur']
             if auteur:
-                records = records.add_to_query('@(creator,contributor) ' + auteur)
+                records = records.search_auteur(auteur)
             titre = self.cleaned_data['titre']
             if titre:
-                records = records.add_to_query('@title ' + titre)
+                records = records.search_titre(titre)
             sujet = self.cleaned_data['sujet']
             if sujet:
-                records = records.add_to_query('@subject ' + sujet)
+                records = records.search_sujet(sujet)
             publisher = self.cleaned_data['publisher']
             if publisher:
-                records = records.add_to_query('@publisher ' + publisher)
+                for word in publisher.split():
+                    records = records.filter(publisher__icontains=word)
             discipline = self.cleaned_data['discipline']
             if discipline:
                 records = records.filter_discipline(discipline)
             region = self.cleaned_data['region']
             if region:
                 records = records.filter_region(region)
-        return records.all()
+        return records
+
+    def get_search_regexp(self):
+        """Retourne une expression régulière compilée qui peut servir à
+           chercher les mot-clés recherchés dans un texte."""
+        if self.is_valid():
+            return build_search_regexp(self.cleaned_data['q'])
 
 class ActualiteSearchForm(forms.Form):
     """Formulaire de recherche pour les actualités."""
@@ -80,25 +87,31 @@ class ActualiteSearchForm(forms.Form):
     def get_query_set(self):
         """Retourne l'ensemble des actualités qui correspondent aux valeurs
            entrées dans le formulaire."""
-        actualites = Actualite.objects
+        actualites = Actualite.objects.filter(visible=True)
         if self.is_valid():
-            q = self.cleaned_data['q']
-            if q:
-                actualites = actualites.search(q)
+            query = self.cleaned_data['q']
+            if query:
+                actualites = actualites.search(query)
+            date_min = self.cleaned_data['date_min']
+            if date_min:
+                actualites = actualites.filter(date__gte=date_min)
+            date_max = self.cleaned_data['date_max']
+            if date_max:
+                actualites = actualites.filter(date__lte=date_max)
             discipline = self.cleaned_data['discipline']
             if discipline:
                 actualites = actualites.filter_discipline(discipline)
             region = self.cleaned_data['region']
             if region:
                 actualites = actualites.filter_region(region)
-            date_min = self.cleaned_data['date_min']
-            if date_min:
-                actualites = actualites.filter_date(min=date_min)
-            date_max = self.cleaned_data['date_max']
-            if date_max:
-                actualites = actualites.filter_date(max=date_max)
-        return actualites.all()
+        return actualites
     
+    def get_search_regexp(self):
+        """Retourne une expression régulière compilée qui peut servir à
+           chercher les mot-clés recherchés dans un texte."""
+        if self.is_valid():
+            return build_search_regexp(self.cleaned_data['q'])
+
 class EvenementSearchForm(forms.Form):
     """Formulaire de recherche pour les évènements."""
 
@@ -114,30 +127,36 @@ class EvenementSearchForm(forms.Form):
     def get_query_set(self):
         """Retourne l'ensemble des évènements qui correspondent aux valeurs
            entrées dans le formulaire."""
-        evenements = Evenement.objects
+        evenements = Evenement.objects.filter(approuve=True)
         if self.is_valid():
             query = self.cleaned_data['q']
             if query:
                 evenements = evenements.search(query)
             titre = self.cleaned_data['titre']
             if titre:
-                evenements = evenements.add_to_query('@titre ' + titre)
-            discipline = self.cleaned_data['discipline']
-            if discipline:
-                evenements = evenements.filter_discipline(discipline)
-            region = self.cleaned_data['region']
-            if region:
-                evenements = evenements.filter_region(region)
+                evenements = evenements.search_titre(titre)
             type = self.cleaned_data['type']
             if type:
-                evenements = evenements.filter_type(type)
+                evenements = evenements.filter(type=type)
             date_min = self.cleaned_data['date_min']
             if date_min:
-                evenements = evenements.filter_debut(min=date_min)
+                evenements = evenements.filter(debut__gte=date_min)
             date_max = self.cleaned_data['date_max']
             if date_max:
-                evenements = evenements.filter_debut(max=date_max)
-        return evenements.all()
+                evenements = evenements.filter(debut__lte=date_max)
+            discipline = self.cleaned_data['discipline']
+            if discipline:
+                evenements = evenements.filter_discipline(discipline)
+            region = self.cleaned_data['region']
+            if region:
+                evenements = evenements.filter_region(region)
+        return evenements
+
+    def get_search_regexp(self):
+        """Retourne une expression régulière compilée qui peut servir à
+           chercher les mot-clés recherchés dans un texte."""
+        if self.is_valid():
+            return build_search_regexp(self.cleaned_data['q'])
 
 ###
 
index eda784f..65804a8 100644 (file)
@@ -2,7 +2,6 @@
 import urllib, httplib, time, simplejson, pprint, math, re
 from django.core.urlresolvers import reverse
 from django.conf import settings
-from django.utils.safestring import mark_safe
 from auf_savoirs_en_partage.backend_config import RESOURCES
 from sep import SEP
 from utils import smart_str
@@ -183,7 +182,7 @@ def build_search_regexp(query):
 
         # Faire ceci après avoir traité les caractères accentués...
         part = part.replace('a', u'[aàâÀÂ]')
-        part = part.replace('e', u'[eéèëêÉÊÈ]')
+        part = part.replace('e', u'[eéèëêÉÊ]')
         part = part.replace('i', u'[iïîÎ]')
         part = part.replace('o', u'[oôÔ]')
         part = part.replace('u', u'[uûüù]')
@@ -191,14 +190,3 @@ def build_search_regexp(query):
 
         parts.append(part)
     return re.compile('|'.join(parts), re.I) 
-
-def excerpt_function(manager, words):
-    """Construit une fonction qui extrait la partie pertinente d'un texte
-       suite à une recherche textuelle."""
-    qs = manager.get_sphinx_query_set()
-    client = qs._get_sphinx_client()
-    index = qs._index
-    def excerpt(text):
-        return mark_safe(client.BuildExcerpts([text], index, words)[0])
-    return excerpt
-
index fe06ec3..82fc289 100644 (file)
@@ -1,29 +1,16 @@
 # -*- encoding: utf-8 -*-
-import caldav
-import datetime
-import operator
-import os
-import pytz
-import random
-import simplejson
-import time
-import uuid
-import vobject
-from backend_config import RESOURCES
+import simplejson, uuid, datetime, caldav, vobject, uuid, random, operator, pytz, os
 from babel.dates import get_timezone_name
-from caldav.lib import error
-from datamaster_modeles.models import Thematique, Pays, Region
 from django.contrib.auth.models import User
 from django.db import models
 from django.db.models import Q, Max
 from django.db.models.signals import pre_delete
-from django.utils.encoding import smart_unicode
-from djangosphinx.models import SphinxQuerySet
+from auf_savoirs_en_partage.backend_config import RESOURCES
 from savoirs.globals import META
-from savoirs.lib.calendrier import combine
 from settings import CALENDRIER_URL, SITE_ROOT_URL
-
-# Fonctionnalités communes à tous les query sets
+from datamaster_modeles.models import Thematique, Pays, Region
+from lib.calendrier import combine
+from caldav.lib import error
 
 class RandomQuerySetMixin(object):
     """Mixin pour les modèles.
@@ -38,59 +25,6 @@ class RandomQuerySetMixin(object):
         positions = random.sample(xrange(count), min(n, count))
         return [self[p] for p in positions]
 
-class SEPQuerySet(models.query.QuerySet, RandomQuerySetMixin):
-    pass
-
-class SEPSphinxQuerySet(SphinxQuerySet, RandomQuerySetMixin):
-    """Fonctionnalités communes aux query sets de Sphinx."""
-
-    def __init__(self, model=None, index=None, weights=None):
-        SphinxQuerySet.__init__(self, model=model, index=index,
-                                mode='SPH_MATCH_EXTENDED2',
-                                rankmode='SPH_RANK_PROXIMITY_BM25',
-                                weights=weights)
-
-    def add_to_query(self, query):
-        """Ajoute une partie à la requête texte."""
-        new_query = smart_unicode(self._query) + ' ' + query if self._query else query
-        return self.query(new_query)
-
-    def search(self, text):
-        """Recherche ``text`` dans tous les champs."""
-        return self.add_to_query('@* ' + text)
-
-    def filter_discipline(self, discipline):
-        """Par défaut, le filtre par discipline cherche le nom de la
-           discipline dans tous les champs."""
-        return self.search('"%s"' % discipline.nom)
-
-    def filter_region(self, region):
-        """Par défaut, le filtre par région cherche le nom de la région dans
-           tous les champs."""
-        return self.search('"%s"' % region.nom)
-
-class SEPManager(models.Manager):
-    """Lorsque les méthodes ``search``, ``filter_region`` et
-       ``filter_discipline`` sont appelées sur ce manager, le query set
-       Sphinx est créé, sinon, c'est le query set Django qui est créé."""
-
-    def query(self, query):
-        return self.get_sphinx_query_set().query(query)
-
-    def add_to_query(self, query):
-        return self.get_sphinx_query_set().add_to_query(query)
-
-    def search(self, text):
-        return self.get_sphinx_query_set().search(text)
-
-    def filter_region(self, region):
-        return self.get_sphinx_query_set().filter_region(region)
-
-    def filter_discipline(self, discipline):
-        return self.get_sphinx_query_set().filter_discipline(discipline)
-
-# Disciplines
-
 class Discipline(models.Model):
     id = models.IntegerField(primary_key=True, db_column='id_discipline')
     nom = models.CharField(max_length=765, db_column='nom_discipline')
@@ -102,8 +36,6 @@ class Discipline(models.Model):
         db_table = u'discipline'
         ordering = ["nom",]
 
-# Actualités
-
 class SourceActualite(models.Model):
     nom = models.CharField(max_length=255)
     url = models.CharField(max_length=255)
@@ -111,40 +43,56 @@ class SourceActualite(models.Model):
     def __unicode__(self,):
         return u"%s" % self.nom
 
-class ActualiteQuerySet(SEPQuerySet):
+class ActualiteManager(models.Manager):
+    
+    def get_query_set(self):
+        return ActualiteQuerySet(self.model)
 
-    def filter_date(self, min=None, max=None):
-        qs = self
-        if min:
-            qs = qs.filter(date__gte=min)
-        if max:
-            qs = qs.filter(date__lte=max)
-        return qs
+    def search(self, text):
+        return self.get_query_set().search(text)
 
-class ActualiteSphinxQuerySet(SEPSphinxQuerySet):
+    def filter_region(self, region):
+        return self.get_query_set().filter_region(region)
 
-    def __init__(self, model=None):
-        SEPSphinxQuerySet.__init__(self, model=model, index='savoirsenpartage_actualites',
-                                   weights=dict(titre=3))
+    def filter_discipline(self, discipline):
+        return self.get_query_set().filter_discipline(discipline)
 
-    def filter_date(self, min=None, max=None):
-        qs = self
-        if min:
-            qs = qs.filter(date__gte=min.toordinal()+365)
-        if max:
-            qs = qs.filter(date__lte=max.toordinal()+365)
-        return qs
+class ActualiteQuerySet(models.query.QuerySet, RandomQuerySetMixin):
 
-class ActualiteManager(SEPManager):
-    
-    def get_query_set(self):
-        return ActualiteQuerySet(self.model).filter(visible=True)
+    def search(self, text):
+        q = None
+        for word in text.split():
+            part = (Q(titre__icontains=word) | Q(texte__icontains=word) |
+                    Q(regions__nom__icontains=word) | Q(disciplines__nom__icontains=word))
+            if q is None:
+                q = part
+            else:
+                q = q & part
+        return self.filter(q).distinct() if q is not None else self
 
-    def get_sphinx_query_set(self):
-        return ActualiteSphinxQuerySet(self.model).order_by('-date')
+    def filter_discipline(self, discipline):
+        """Ne conserve que les actualités dans la discipline donnée.
+           
+        Si ``disicipline`` est None, ce filtre n'a aucun effet."""
+        if discipline is None:
+            return self
+        if not isinstance(discipline, Discipline):
+            discipline = Discipline.objects.get(pk=discipline)
+        return self.filter(Q(disciplines=discipline) |
+                           Q(titre__icontains=discipline.nom) |
+                           Q(texte__icontains=discipline.nom)).distinct()
 
-    def filter_date(self, min=None, max=None):
-        return self.get_query_set().filter_date(min=min, max=max)
+    def filter_region(self, region):
+        """Ne conserve que les actualités dans la région donnée.
+           
+        Si ``region`` est None, ce filtre n'a aucun effet."""
+        if region is None:
+            return self
+        if not isinstance(region, Region):
+            region = Region.objects.get(pk=region)
+        return self.filter(Q(regions=region) |
+                           Q(titre__icontains=region.nom) |
+                           Q(texte__icontains=region.nom)).distinct()
 
 class Actualite(models.Model):
     id = models.AutoField(primary_key=True, db_column='id_actualite')
@@ -159,7 +107,6 @@ class Actualite(models.Model):
     regions = models.ManyToManyField(Region, blank=True, related_name="actualites", verbose_name='régions')
 
     objects = ActualiteManager()
-    all_objects = models.Manager()
 
     class Meta:
         db_table = u'actualite'
@@ -174,51 +121,73 @@ class Actualite(models.Model):
     def assigner_regions(self, regions):
         self.regions.add(*regions)
 
-# Agenda
+class EvenementManager(models.Manager):
 
-class EvenementQuerySet(SEPQuerySet):
+    def get_query_set(self):
+        return EvenementQuerySet(self.model)
 
-    def filter_type(self, type):
-        return self.filter(type=type)
+    def search(self, text):
+        return self.get_query_set().search(text)
 
-    def filter_debut(self, min=None, max=None):
-        qs = self
-        if min:
-            qs = qs.filter(debut__gte=min)
-        if max:
-            qs = qs.filter(debut__lt=max+datetime.timedelta(days=1))
-        return qs
+    def filter_region(self, region):
+        return self.get_query_set().filter_region(region)
 
-class EvenementSphinxQuerySet(SEPSphinxQuerySet):
+    def filter_discipline(self, discipline):
+        return self.get_query_set().filter_discipline(discipline)
 
-    def __init__(self, model=None):
-        SEPSphinxQuerySet.__init__(self, model=model, index='savoirsenpartage_evenements',
-                                   weights=dict(titre=3))
+class EvenementQuerySet(models.query.QuerySet, RandomQuerySetMixin):
 
-    def filter_type(self, type):
-        return self.add_to_query('@type "%s"' % type)
-    
-    def filter_debut(self, min=None, max=None):
+    def search(self, text):
+        q = None
+        for word in text.split():
+            part = (Q(titre__icontains=word) | 
+                    Q(mots_cles__icontains=word) |
+                    Q(discipline__nom__icontains=word) | 
+                    Q(discipline_secondaire__nom__icontains=word) |
+                    Q(type__icontains=word) |
+                    Q(lieu__icontains=word) |
+                    Q(description__icontains=word) |
+                    Q(contact__icontains=word) |
+                    Q(regions__nom__icontains=word))
+            if q is None:
+                q = part
+            else:
+                q = q & part
+        return self.filter(q).distinct() if q is not None else self
+
+    def search_titre(self, text):
         qs = self
-        if min:
-            qs = qs.filter(debut__gte=min.toordinal()+365)
-        if max:
-            qs = qs.filter(debut__lte=max.toordinal()+365)
+        for word in text.split():
+            qs = qs.filter(titre__icontains=word)
         return qs
 
-class EvenementManager(SEPManager):
-
-    def get_query_set(self):
-        return EvenementQuerySet(self.model).filter(approuve=True)
-
-    def get_sphinx_query_set(self):
-        return EvenementSphinxQuerySet(self.model).order_by('-debut')
-
-    def filter_type(self, type):
-        return self.get_query_set().filter_type(type)
+    def filter_discipline(self, discipline):
+        """Ne conserve que les évènements dans la discipline donnée.
+           
+        Si ``disicipline`` est None, ce filtre n'a aucun effet."""
+        if discipline is None:
+            return self
+        if not isinstance(discipline, Discipline):
+            discipline = Discipline.objects.get(pk=discipline)
+        return self.filter(Q(discipline=discipline) |
+                           Q(discipline_secondaire=discipline) |
+                           Q(titre__icontains=discipline.nom) |
+                           Q(mots_cles__icontains=discipline.nom) |
+                           Q(description__icontains=discipline.nom))
 
-    def filter_debut(self, min=None, max=None):
-        return self.get_query_set().filter_debut(min=min, max=max)
+    def filter_region(self, region):
+        """Ne conserve que les évènements dans la région donnée.
+           
+        Si ``region`` est None, ce filtre n'a aucun effet."""
+        if region is None:
+            return self
+        if not isinstance(region, Region):
+            region = Region.objects.get(pk=region)
+        return self.filter(Q(regions=region) |
+                           Q(titre__icontains=region.nom) |
+                           Q(mots_cles__icontains=region.nom) |
+                           Q(description__icontains=region.nom) |
+                           Q(lieu__icontains=region.nom)).distinct()
 
 def build_time_zone_choices():
     fr_names = set()
@@ -243,7 +212,7 @@ class Evenement(models.Model):
                     (u'Conférence', u'Conférence'),
                     (u'Appel à contribution', u'Appel à contribution'),
                     (u'Journée d\'étude', u'Journée d\'étude'),
-                    (u'None', u'Autre'))
+                    (None, u'Autre'))
     TIME_ZONE_CHOICES = build_time_zone_choices()
 
     uid = models.CharField(max_length=255, default=str(uuid.uuid1()))
@@ -267,7 +236,6 @@ class Evenement(models.Model):
     regions = models.ManyToManyField(Region, blank=True, related_name="evenements", verbose_name='régions')
 
     objects = EvenementManager()
-    all_objects = models.Manager()
 
     class Meta:
         ordering = ['-debut']
@@ -382,14 +350,15 @@ class Evenement(models.Model):
             self.discipline = disciplines[0]
             self.discipline_secondaire = disciplines[1]
 
+
+# Surcharge du comportement de suppression
+# La méthode de connexion par signals est préférable à surcharger la méthode delete()
+# car dans le cas de la suppression par lots, cell-ci n'est pas invoquée
 def delete_vevent(sender, instance, *args, **kwargs):
-    # Surcharge du comportement de suppression
-    # La méthode de connexion par signals est préférable à surcharger la méthode delete()
-    # car dans le cas de la suppression par lots, cell-ci n'est pas invoquée
     instance.delete_vevent()
-pre_delete.connect(delete_vevent, sender=Evenement) 
 
-# Ressources
+pre_delete.connect(delete_vevent, sender = Evenement) 
+
 
 class ListSet(models.Model):
     spec = models.CharField(primary_key = True, max_length = 255)
@@ -400,24 +369,141 @@ class ListSet(models.Model):
     def __unicode__(self,):
         return self.name
 
-class RecordSphinxQuerySet(SEPSphinxQuerySet):
+class RecordManager(models.Manager):
+    
+    def get_query_set(self):
+        return RecordQuerySet(self.model)
 
-    def __init__(self, model=None):
-        SEPSphinxQuerySet.__init__(self, model=model, index='savoirsenpartage_ressources',
-                                   weights=dict(title=3))
+    def search(self, text):
+        return self.get_query_set().search(text)
 
-class RecordManager(SEPManager):
+    def validated(self):
+        return self.get_query_set().validated()
 
-    def get_query_set(self):
+    def filter_region(self, region):
+        return self.get_query_set().filter_region(region)
+
+    def filter_discipline(self, discipline):
+        return self.get_query_set().filter_discipline(discipline)
+
+class RecordQuerySet(models.query.QuerySet, RandomQuerySetMixin):
+
+    def search(self, text):
+        qs = self
+        words = text.split()
+
+        # Ne garder que les ressources qui contiennent tous les mots
+        # demandés.
+        q = None
+        for word in words:
+            matching_pays = list(Pays.objects.filter(Q(nom__icontains=word) | Q(region__nom__icontains=word)).values_list('pk', flat=True))
+            part = (Q(title__icontains=word) | Q(description__icontains=word) |
+                    Q(creator__icontains=word) | Q(contributor__icontains=word) |
+                    Q(subject__icontains=word) | Q(disciplines__nom__icontains=word) |
+                    Q(regions__nom__icontains=word) | Q(pays__in=matching_pays) |
+                    Q(publisher__icontains=word))
+            if q is None:
+                q = part
+            else:
+                q = q & part
+        if q is not None:
+            qs = qs.filter(q).distinct()
+
+        # On donne un point pour chaque mot présent dans le titre.
+        if words:
+            score_expr = ' + '.join(['(title LIKE %s)'] * len(words))
+            score_params = ['%' + word + '%' for word in words]
+            qs = qs.extra(
+                select={'score': score_expr},
+                select_params=score_params
+            ).order_by('-score')
+        return qs
+
+    def search_auteur(self, text):
+        qs = self
+        for word in text.split():
+            qs = qs.filter(Q(creator__icontains=word) | Q(contributor__icontains=word))
+        return qs
+
+    def search_sujet(self, text):
+        qs = self
+        for word in text.split():
+            qs = qs.filter(subject__icontains=word)
+        return qs
+
+    def search_titre(self, text):
+        qs = self
+        for word in text.split():
+            qs = qs.filter(title__icontains=word)
+        return qs
+            
+    def filter_discipline(self, discipline):
+        """Ne conserve que les ressources dans la discipline donnée.
+           
+        Si ``disicipline`` est None, ce filtre n'a aucun effet."""
+        if discipline is None:
+            return self
+        if not isinstance(discipline, Discipline):
+            discipline = Discipline.objects.get(pk=discipline)
+        return self.filter(Q(disciplines=discipline) |
+                           Q(title__icontains=discipline.nom) |
+                           Q(description__icontains=discipline.nom) |
+                           Q(subject__icontains=discipline.nom)).distinct()
+
+    def filter_region(self, region):
+        """Ne conserve que les ressources dans la région donnée.
+           
+        Si ``region`` est None, ce filtre n'a aucun effet."""
+        if region is None:
+            return self
+        if not isinstance(region, Region):
+            region = Region.objects.get(pk=region)
+        return self.filter(Q(pays__region=region) |
+                           Q(regions=region) |
+                           Q(title__icontains=region.nom) |
+                           Q(description__icontains=region.nom) |
+                           Q(subject__icontains=region.nom)).distinct()
+
+    def validated(self):
         """Ne garder que les ressources validées et qui sont soit dans aucun
            listset ou au moins dans un listset validé."""
-        qs = SEPQuerySet(self.model)
-        qs = qs.filter(validated=True)
+        qs = self.filter(validated=True)
         qs = qs.filter(Q(listsets__isnull=True) | Q(listsets__validated=True))
         return qs.distinct()
 
-    def get_sphinx_query_set(self):
-        return RecordSphinxQuerySet(self.model)
+    def filter(self, *args, **kwargs):
+        """Gère des filtres supplémentaires pour l'admin.
+           
+        C'est la seule façon que j'ai trouvée de contourner les mécanismes
+        de recherche de l'admin."""
+        search = kwargs.pop('admin_search', None)
+        search_titre = kwargs.pop('admin_search_titre', None)
+        search_sujet = kwargs.pop('admin_search_sujet', None)
+        search_description = kwargs.pop('admin_search_description', None)
+        search_auteur = kwargs.pop('admin_search_auteur', None)
+
+        if search:
+            qs = self
+            search_all = not (search_titre or search_description or search_sujet or search_auteur)
+            fields = []
+            if search_titre or search_all:
+                fields += ['title', 'alt_title']
+            if search_description or search_all:
+                fields += ['description', 'abstract']
+            if search_sujet or search_all:
+                fields += ['subject']
+            if search_auteur or search_all:
+                fields += ['creator', 'contributor']
+
+            for bit in search.split():
+                or_queries = [Q(**{field + '__icontains': bit}) for field in fields]
+                qs = qs.filter(reduce(operator.or_, or_queries))
+
+            if args or kwargs:
+                qs = super(RecordQuerySet, qs).filter(*args, **kwargs)
+            return qs
+        else:
+            return super(RecordQuerySet, self).filter(*args, **kwargs)
 
 class Record(models.Model):
     
@@ -459,9 +545,8 @@ class Record(models.Model):
     pays = models.ManyToManyField(Pays, blank=True)
     regions = models.ManyToManyField(Region, blank=True, verbose_name='régions')
 
-    # Managers
+    # Manager
     objects = RecordManager()
-    all_objects = models.Manager()
 
     class Meta:
         verbose_name = 'ressource'
index c540926..409bb02 100644 (file)
@@ -1,8 +1,8 @@
 # -*- encoding: utf-8 -*-
+from datetime import datetime
 from django.core.urlresolvers import reverse
 from django.contrib.syndication.feeds import Feed
-from savoirs.models import Actualite
-from savoirs.lib.calendrier import evenements
+from savoirs.models import Actualite, Evenement
 from datetime import datetime, time
 
 class FilActualite(Feed):
@@ -36,13 +36,13 @@ class FilEvenement(Feed):
     description_template = "savoirs/rss_evenement_description.html"
 
     def items(self):
-        return evenements()
+        return Evenement.objects.filter(approuve=True, debut__gte=datetime.now())
 
     def item_link(self, item):
-        return reverse('savoirs.views.evenement', args=[item.uid.value])
+        return reverse('savoirs.views.evenement', args=[item.id])
 
     def item_pubdate(self,item):
-        return item.dtstart.value
+        return item.debut
 
     def item_author_name(self,item):
         return ""
index 8d173ac..90830f3 100644 (file)
@@ -127,8 +127,3 @@ def change_discipline(path, discipline):
     if not rest.startswith('/recherche'):
         rest = '/'
     return discipline_bit + region_bit + rest
-
-@register.filter
-def apply(value, func):
-    """Applique une fonction arbitraire à la valeur filtrée."""
-    return func(value)
index 688dc70..a7ea72b 100644 (file)
@@ -10,7 +10,7 @@ from django.shortcuts import get_object_or_404
 from django.utils.safestring import mark_safe
 from django import forms
 from django.conf import settings
-from lib.recherche import google_search, build_search_regexp, excerpt_function
+from lib.recherche import google_search, build_search_regexp
 from lib import sep
 from lib.calendrier import evenements, evenement_info, combine
 from savoirs.globals import configuration
@@ -24,30 +24,13 @@ from sitotheque.models import Site
 
 def index(request, discipline=None, region=None):
     """Page d'accueil"""
-    actualites = Actualite.objects
-    evenements = Evenement.objects
-    ressources = Record.objects
-    chercheurs = Chercheur.objects
-    sites = Site.objects
-    if discipline:
-        discipline = Discipline.objects.get(pk=discipline)
-        actualites = actualites.filter_discipline(discipline)
-        evenements = evenements.filter_discipline(discipline)
-        ressources = ressources.filter_discipline(discipline)
-        chercheurs = chercheurs.filter_discipline(discipline)
-        sites = sites.filter_discipline(discipline)
-    if region:
-        region = Region.objects.get(pk=region)
-        actualites = actualites.filter_region(region)
-        evenements = evenements.filter_region(region)
-        ressources = ressources.filter_region(region)
-        chercheurs = chercheurs.filter_region(region)
-        sites = sites.filter_region(region)
-    actualites = actualites.order_by('-date')[0:4]
-    evenements = evenements.order_by('-debut')[0:4]
-    ressources = ressources.order_by('-id')[0:4]
-    chercheurs = chercheurs.order_by('-date_modification')[0:10]
-    sites = sites.order_by('-date_maj')[0:4]
+    delta = datetime.timedelta(days = 90)
+    oldest = datetime.date.today() - delta
+    actualites = Actualite.objects.filter(visible=True, date__gt=oldest).filter_discipline(discipline).filter_region(region)[:4]
+    evenements = Evenement.objects.filter(approuve=True).filter_discipline(discipline).filter_region(region)[:4]
+    ressources = Record.objects.validated().filter_discipline(discipline).filter_region(region).random(4)
+    chercheurs = Chercheur.objects.filter_discipline(discipline).filter_region(region).order_by('-date_modification')[:10]
+    sites = Site.objects.filter_discipline(discipline).filter_region(region).random(4)
     return render_to_response(
         "savoirs/index.html",
         dict(actualites=actualites, evenements=evenements,
@@ -85,54 +68,39 @@ def recherche(request, discipline=None, region=None):
             kwargs['region'] = region
         return HttpResponseRedirect(reverse('savoirs.views.index', kwargs=kwargs))
 
-    actualites = Actualite.objects.search(query)
-    evenements = Evenement.objects.search(query)
-    ressources = Record.objects.search(query)
-    chercheurs = Chercheur.objects.search(query)
-    sites = Site.objects.search(query)
-    if discipline:
-        discipline = Discipline.objects.get(pk=discipline)
-        actualites = actualites.filter_discipline(discipline)
-        evenements = evenements.filter_discipline(discipline)
-        ressources = ressources.filter_discipline(discipline)
-        chercheurs = chercheurs.filter_discipline(discipline)
-        sites = sites.filter_discipline(discipline)
-    if region:
-        region = Region.objects.get(pk=region)
-        actualites = actualites.filter_region(region)
-        evenements = evenements.filter_region(region)
-        ressources = ressources.filter_region(region)
-        chercheurs = chercheurs.filter_region(region)
-        sites = sites.filter_region(region)
+    ressources = Record.objects.validated().filter_discipline(discipline).filter_region(region).search(query)
+    actualites = Actualite.objects.filter(visible=1).filter_discipline(discipline).filter_region(region).search(query)
+    evenements = Evenement.objects.filter(approuve=1).filter_discipline(discipline).filter_region(region).search(query)
+    chercheurs = Chercheur.objects.filter_discipline(discipline).filter_region(region).search(query)
+    sites = Site.objects.filter_discipline(discipline).filter_region(region).search(query)
     try:
         sites_auf = google_search(0, query)['results']
     except:
         sites_auf = []
+    search_regexp = build_search_regexp(query)
 
     # Bâtissons une query string pour les liens vers les briques
     params = {}
     if query:
         params['q'] = query
     if discipline:
-        params['discipline'] = unicode(discipline.id)
+        params['discipline'] = discipline
     if region:
-        params['region'] = unicode(region.id)
+        params['region'] = region
     if params:
         briques_query_string = mark_safe('?' + '&'.join(k + '=' + v.replace('"', '&quot;') for (k, v) in params.iteritems()))
     else:
         briques_query_string = None
         
-    excerpt = excerpt_function(Record.objects, query)
-
     return render_to_response(
         "savoirs/recherche.html",
-        dict(q=query, excerpt=excerpt,
-             ressources=ressources[0:5], total_ressources=ressources.count(), 
-             evenements=evenements[0:5], total_evenements=evenements.count(),
-             chercheurs=chercheurs[0:10], total_chercheurs=chercheurs.count(),
-             actualites=actualites[0:5], total_actualites=actualites.count(),
-             sites=sites[0:5], total_sites=sites.count(),
-             sites_auf=sites_auf[0:5], briques_query_string=briques_query_string),
+        dict(q=query, search_regexp=search_regexp,
+             ressources=ressources[:5], total_ressources=ressources.count(), 
+             evenements=evenements[:5], total_evenements=evenements.count(),
+             chercheurs=chercheurs[:10], total_chercheurs=chercheurs.count(),
+             actualites=actualites[:5], total_actualites=actualites.count(),
+             sites=sites[:5], total_sites=sites.count(),
+             sites_auf=sites_auf[:5], briques_query_string=briques_query_string),
         context_instance = RequestContext(request)
     )
 
@@ -152,15 +120,12 @@ def ressource_index(request):
     search_form = RecordSearchForm(request.GET)
     ressources = search_form.get_query_set()
     nb_resultats = ressources.count()
-    if search_form.is_valid():
-        excerpt = excerpt_function(Record.objects, search_form.cleaned_data['q'])
-    else:
-        excerpt = lambda x: x
+    search_regexp = search_form.get_search_regexp()
     return render_to_response(
         "savoirs/ressource_index.html", 
-        dict(search_form=search_form, ressources=ressources,
-             nb_resultats=nb_resultats, excerpt=excerpt),
-        context_instance=RequestContext(request)
+        {'search_form': search_form, 'ressources': ressources,
+         'nb_resultats': nb_resultats, 'search_regexp': search_regexp},
+        context_instance = RequestContext(request)
     )
 
 def ressource_retrieve(request, id):
@@ -189,25 +154,22 @@ def informations (request):
 def actualite_index(request):
     search_form = ActualiteSearchForm(request.GET)
     actualites = search_form.get_query_set()
-    if search_form.is_valid():
-        excerpt = excerpt_function(Actualite.objects, search_form.cleaned_data['q'])
-    else:
-        excerpt = lambda x: x
+    search_regexp = search_form.get_search_regexp()
     return render_to_response(
         "savoirs/actualite_index.html",
         dict(actualites=actualites, search_form=search_form,
-             excerpt=excerpt, nb_resultats=actualites.count()),
+             search_regexp=search_regexp, nb_resultats=actualites.count()),
         context_instance = RequestContext(request))
 
 # agenda
 def evenement_index(request):
     search_form = EvenementSearchForm(request.GET)
     evenements = search_form.get_query_set()
-    excerpt = excerpt_function(Evenement.objects, search_form.cleaned_data['q'])
+    search_regexp = search_form.get_search_regexp()
     return render_to_response(
         "savoirs/evenement_index.html",
         dict(evenements=evenements, search_form=search_form,
-             excerpt=excerpt, nb_resultats=evenements.count()),
+             search_regexp=search_regexp, nb_resultats=evenements.count()),
         context_instance=RequestContext(request)
     )
                               
diff --git a/auf_savoirs_en_partage/scripts/sphinx.conf.py.in b/auf_savoirs_en_partage/scripts/sphinx.conf.py.in
deleted file mode 100644 (file)
index 04687b0..0000000
+++ /dev/null
@@ -1,225 +0,0 @@
-#!/usr/bin/python
-# coding: utf-8
-# 
-# Ce script compose dynamiquement une configuration pour Sphinx. Il suffit
-# que le fichier soit exécutable pour que Sphinx exécute le script plutôt
-# que de le lire comme un fichier statique.
-#
-# Le manuel de sphinx se trouve au http://sphinxsearch.com/docs/manual-0.9.9.html
-
-import glob
-import os
-import sys
-
-sys.path[0:0] = [
-  "%(directory)s",
-  "%(directory)s/auf_savoirs_en_partage",
-  ]
-os.environ['DJANGO_SETTINGS_MODULE'] = 'production'
-for d in glob.glob("%(directory)s/eggs/*"):
-    sys.path[0:0] = [d,]
-for d in glob.glob("%(directory)s/parts/*"):
-    sys.path[0:0] = [d,]
-
-from django.conf import settings
-
-SQL_HOST = settings.DATABASE_HOST
-SQL_USER = settings.DATABASE_USER
-SQL_PASS = settings.DATABASE_PASSWORD
-SQL_DB = settings.DATABASE_NAME
-DATA_DIR = '/var/lib/sphinxsearch/data'
-
-def multiline(s):
-    """Place un marqueur de continuation avant chaque saut de ligne."""
-    return s.replace("\n", "\\\n")
-
-def emit_source(name, sql_query, sql_query_info=None, sql_attr_multi=None, sql_attr_uint=None):
-    print '''
-source %%(name)s
-{
-    type = mysql
-    sql_host = %%(sql_host)s
-    sql_user = %%(sql_user)s
-    sql_pass = %%(sql_pass)s
-    sql_db = %%(sql_db)s
-    sql_query_pre = SET NAMES utf8
-    sql_query_pre = SET SESSION query_cache_type=OFF
-    sql_query = %%(sql_query)s
-''' %% dict(name=name, sql_host=SQL_HOST, sql_user=SQL_USER,
-            sql_pass=SQL_PASS, sql_db=SQL_DB, sql_query=multiline(sql_query))
-
-    if sql_query_info:
-        print '    sql_query_info = ' + sql_query_info
-
-    if sql_attr_multi:
-        for attr in sql_attr_multi:
-            print '    sql_attr_multi = uint %%s from field' %% attr
-
-    if sql_attr_uint:
-        for attr in sql_attr_uint:
-            print '    sql_attr_uint = ' + attr
-    
-    print '}'
-
-def emit_index(name):
-    print '''
-index %%(name)s
-{
-    morphology = libstemmer_fr
-    charset_type = utf-8
-    charset_table = 0..9, A..Z->a..z, _, a..z, \\
-                    U+C0->a, U+C2->a, U+E0->a, U+E2->a, \\
-                    U+C7->c, U+E7->c, \\
-                    U+C8->e, U+C9->e, U+CA->e, U+E8->e, U+E9->e, U+EA->e, U+EB->e, \\
-                    U+CE->i, U+EE->i, U+EF->i, \\
-                    U+D4->o, U+F4->o, \\
-                    U+F9->u, U+FB->u, U+FC->u
-    source = %%(name)s
-    path = %%(path)s
-}''' %% dict(name=name, path=os.path.join(DATA_DIR, name))
-
-emit_source('savoirsenpartage_ressources', 
-            '''SELECT r.id AS id, 
-                      r.title AS title, 
-                      r.description AS description, 
-                      r.creator AS creator, 
-                      r.contributor AS contributor, 
-                      r.subject AS subject, 
-                      r.publisher AS publisher, 
-                      GROUP_CONCAT(DISTINCT d.nom_discipline) AS disciplines, 
-                      GROUP_CONCAT(DISTINCT d.id_discipline) AS discipline_ids,
-                      GROUP_CONCAT(DISTINCT p.nom) AS pays, 
-                      GROUP_CONCAT(DISTINCT reg.nom) AS regions,
-                      GROUP_CONCAT(DISTINCT reg.id) AS region_ids
-                FROM savoirs_record r 
-                LEFT JOIN savoirs_record_disciplines rd ON rd.record_id = r.id 
-                LEFT JOIN discipline d ON d.id_discipline = rd.discipline_id 
-                LEFT JOIN savoirs_record_pays rp ON rp.record_id = r.id 
-                LEFT JOIN ref_pays p ON p.id = rp.pays_id 
-                LEFT JOIN savoirs_record_regions rr ON rr.record_id = r.id 
-                LEFT JOIN ref_region reg ON reg.id = rr.region_id OR reg.id = p.region 
-                LEFT JOIN savoirs_record_listsets rl ON rl.record_id = r.id
-                LEFT JOIN savoirs_listset l ON l.spec = rl.listset_id
-                WHERE r.validated AND (l.spec IS NULL OR l.validated)
-                GROUP BY r.id''',
-            sql_query_info='SELECT * from savoirs_record WHERE id=$id',
-            sql_attr_multi=['discipline_ids', 'region_ids']
-            )
-
-emit_source('savoirsenpartage_actualites',
-            '''SELECT a.id_actualite AS id, 
-                      a.titre_actualite AS titre, 
-                      a.texte_actualite AS texte, 
-                      TO_DAYS(a.date_actualite) AS date,
-                      GROUP_CONCAT(DISTINCT r.nom) AS regions, 
-                      GROUP_CONCAT(DISTINCT d.nom_discipline) AS disciplines
-               FROM actualite a 
-               LEFT JOIN actualite_regions ar ON ar.actualite_id = a.id_actualite 
-               LEFT JOIN ref_region r ON r.id = ar.region_id 
-               LEFT JOIN actualite_disciplines ad ON ad.actualite_id = a.id_actualite 
-               LEFT JOIN discipline d ON d.id_discipline = ad.discipline_id
-               WHERE a.visible_actualite
-               GROUP BY a.id_actualite''',
-            sql_query_info='SELECT * from actualite WHERE id_actualite=$id',
-            sql_attr_uint=['date']
-           )
-
-emit_source('savoirsenpartage_evenements',
-            '''SELECT e.id AS id,
-                      e.titre AS titre,
-                      e.mots_cles AS mots_cles,
-                      e.type AS type,
-                      e.lieu AS lieu,
-                      e.description AS description,
-                      e.contact AS contact,
-                      CONCAT_WS(',', d.nom_discipline, d2.nom_discipline) AS disciplines,
-                      GROUP_CONCAT(DISTINCT r.nom) AS regions,
-                      TO_DAYS(DATE(e.debut)) AS debut
-               FROM savoirs_evenement e
-               LEFT JOIN discipline d ON d.id_discipline = e.discipline_id
-               LEFT JOIN discipline d2 ON d2.id_discipline = e.discipline_secondaire_id
-               LEFT JOIN savoirs_evenement_regions er ON er.evenement_id = e.id
-               LEFT JOIN ref_region r ON r.id = er.region_id
-               WHERE e.approuve
-               GROUP BY e.id''',
-            sql_query_info='SELECT * from savoirs_evenement WHERE id=$id',
-            sql_attr_uint=['debut'])
-            
-emit_source('savoirsenpartage_chercheurs',
-            '''SELECT c.id AS id,
-                      p.nom AS nom,
-                      p.prenom AS prenom,
-                      c.theme_recherche AS theme_recherche,
-                      c.groupe_recherche AS groupe_recherche,
-                      c.mots_cles AS mots_cles,
-                      c.membre_association_francophone_details AS membre_association_francophone_details,
-                      c.membre_reseau_institutionnel_details AS membre_reseau_institutionnel_details,
-                      c.expert_oif_details AS expert_oif_details,
-                      c.membre_instance_auf_details AS membre_instance_auf_details,
-                      IFNULL(et.nom, etablissement_autre_nom) AS etablissement,
-                      pays.nom AS pays,
-                      pays.id AS pays_id,
-                      r.nom AS region,
-                      r.id AS region_id,
-                      GROUP_CONCAT(DISTINCT d.nom_discipline) AS disciplines,
-                      CONCAT_WS(pub1.titre, pub2.titre, pub3.titre, pub4.titre) AS publications,
-                      t.titre AS these,
-                      GROUP_CONCAT(DISTINCT g.nom) AS groupes,
-                      GROUP_CONCAT(DISTINCT ex.nom) AS expertises,
-                      GROUP_CONCAT(DISTINCT g.id) AS groupe_ids,
-                      TO_DAYS(c.date_modification) AS date_modification,
-                      CASE pays WHEN 'Nord' THEN 1 
-                                WHEN 'Sud' THEN 2 
-                                END AS nord_sud,
-                      CASE statut WHEN 'enseignant' THEN 1
-                                  WHEN 'etudiant' THEN 2
-                                  WHEN 'independant' THEN 3
-                                  END AS statut,
-                      (ex.id IS NULL) AS expert
-               FROM chercheurs_chercheur c
-               INNER JOIN chercheurs_personne p ON c.personne = p.id
-               LEFT JOIN ref_etablissement et ON et.id = c.etablissement
-               LEFT JOIN ref_pays pays ON pays.id = IFNULL(et.pays, c.etablissement_autre_pays)
-               LEFT JOIN ref_region r ON pays.region = r.id
-               LEFT JOIN discipline d ON d.id_discipline = c.discipline
-               LEFT JOIN chercheurs_publication pub1 ON pub1.id = c.publication1
-               LEFT JOIN chercheurs_publication pub2 ON pub2.id = c.publication2
-               LEFT JOIN chercheurs_publication pub3 ON pub3.id = c.publication3
-               LEFT JOIN chercheurs_publication pub4 ON pub4.id = c.publication4
-               LEFT JOIN chercheurs_publication t ON t.id = c.these
-               LEFT JOIN chercheurs_chercheurgroupe cg ON cg.chercheur = c.id
-               LEFT JOIN chercheurs_groupe g ON g.id = cg.groupe
-               LEFT JOIN chercheurs_expertise ex ON ex.chercheur_id = c.id
-               GROUP BY c.id''',
-            sql_query_info='SELECT * from chercheurs_chercheur WHERE id=$id',
-            sql_attr_multi=['groupe_ids'],
-            sql_attr_uint=['pays_id', 'region_id', 'nord_sud', 'date_modification', 'statut', 'expert'])
-                      
-emit_source('savoirsenpartage_sites',
-            '''SELECT s.id AS id,
-                      s.titre AS titre,
-                      s.description AS description,
-                      s.editeur AS editeur,
-                      s.auteur AS auteur,
-                      s.mots_cles AS mots_cles,
-                      GROUP_CONCAT(DISTINCT d.nom_discipline) AS disciplines,
-                      GROUP_CONCAT(DISTINCT p.nom) AS pays,
-                      GROUP_CONCAT(DISTINCT p.id) AS pays_ids,
-                      GROUP_CONCAT(DISTINCT r.nom) AS regions,
-                      TO_DAYS(s.date_maj) AS date_maj
-               FROM sitotheque_site s
-               LEFT JOIN sitotheque_site_discipline sd ON sd.site_id = s.id
-               LEFT JOIN discipline d ON d.id_discipline = sd.discipline_id
-               LEFT JOIN ref_pays p ON p.id = s.pays
-               LEFT JOIN ref_region r ON r.id = p.region
-               GROUP BY s.id''',
-            'SELECT * FROM sitotheque_site WHERE id=$id',
-            sql_attr_multi=['pays_ids'],
-            sql_attr_uint=['date_maj']
-           )
-
-emit_index('savoirsenpartage_actualites')
-emit_index('savoirsenpartage_ressources')
-emit_index('savoirsenpartage_evenements')
-emit_index('savoirsenpartage_chercheurs')
-emit_index('savoirsenpartage_sites')
index a4e97de..5334d72 100644 (file)
@@ -65,7 +65,6 @@ INSTALLED_APPS = (
     'savoirs',
     'chercheurs',
     'sitotheque',
-    'djangosphinx',
 )
 
 
@@ -93,7 +92,7 @@ AUTHENTICATION_BACKENDS = (
     'authentification.CascadeBackend',
 )
 
-CACHE_BACKEND = 'memcached://localhost:11211'
+CACHE_BACKEND = 'locmem://'
 
 ROA_CUSTOM_ARGS = {'api-key': ROA_API_KEY}
 
@@ -103,7 +102,4 @@ AUTH_PROFILE_MODULE = 'savoirs.Profile'
 
 CONTACT_EMAIL = 'contact-savoirsenpartage@auf.org'
 
-SPHINX_API_VERSION = 0x116
-SPHINX_PORT = 9312
-
 from auf_references_client.settings import *
index d7aac37..5317049 100644 (file)
@@ -14,7 +14,7 @@ class SiteSearchForm(forms.Form):
     def get_query_set(self):
         """Retourne l'ensemble des sites qui correspondent aux valeurs
            entrées dans le formulaire."""
-        sites = Site.objects
+        sites = Site.objects.order_by("titre")
         if self.is_valid():
             q = self.cleaned_data["q"]
             if q:
@@ -27,5 +27,11 @@ class SiteSearchForm(forms.Form):
                 sites = sites.filter_region(region)
             pays = self.cleaned_data["pays"]
             if pays:
-                sites = sites.filter_pays(pays=pays)
-        return sites.all()
+                sites = sites.filter(pays=pays.pk)
+        return sites
+
+    def get_search_regexp(self):
+        """Retourne une expression régulière compilée qui peut servir à
+           chercher les mot-clés recherchés dans un texte."""
+        if self.is_valid():
+            return build_search_regexp(self.cleaned_data['q'])
index cb3f8a1..7dd4b42 100644 (file)
@@ -1,9 +1,8 @@
 # -*- encoding: utf-8 -*-
-from datamaster_modeles.models import *
 from django.db import models
 from django.db.models import Q
-from djangosphinx.models import SphinxSearch
-from savoirs.models import Discipline, SEPManager, SEPSphinxQuerySet, SEPQuerySet
+from datamaster_modeles.models import *
+from savoirs.models import Discipline, RandomQuerySetMixin
 
 TYPE_SITE_CHOICES = (
     ('RV', 'Revue en ligne'), 
@@ -18,29 +17,66 @@ TYPE_SITE_CHOICES = (
     ('AU', 'Autre type de site'),
     )
 
-class SiteQuerySet(SEPQuerySet):
+class SiteManager(models.Manager):
 
-    def filter_pays(self, pays):
-        return self.filter(pays=pays)
+    def get_query_set(self):
+        return SiteQuerySet(self.model)
 
-class SiteSphinxQuerySet(SEPSphinxQuerySet):
+    def search(self, text):
+        return self.get_query_set().search(text)
 
-    def __init__(self, model=None):
-        SEPSphinxQuerySet.__init__(self, model=model, index='savoirsenpartage_sites', weights=dict(titre=3))
+    def filter_region(self, region):
+        return self.get_query_set().filter_region(region)
 
-    def filter_pays(self, pays):
-        return self.filter(pays_ids=pays.id)
+    def filter_discipline(self, discipline):
+        return self.get_query_set().filter_discipline(discipline)
 
-class SiteManager(SEPManager):
+class SiteQuerySet(models.query.QuerySet, RandomQuerySetMixin):
 
-    def get_query_set(self):
-        return SiteQuerySet(self.model)
+    def search(self, text):
+        qs = self
+        q = None
+        for word in text.split():
+            part = (Q(titre__icontains=word) |
+                    Q(description__icontains=word) |
+                    Q(editeur__icontains=word) |
+                    Q(auteur__icontains=word) |
+                    Q(mots_cles__icontains=word) |
+                    Q(discipline__nom__icontains=word) |
+                    Q(pays__nom__icontains=word))
+            if q is None:
+                q = part
+            else:
+                q = q & part
+        if q is not None:
+            qs = qs.filter(q).distinct()
+        return qs
 
-    def get_sphinx_query_set(self):
-        return SiteSphinxQuerySet(self.model)
+    def filter_discipline(self, discipline):
+        """Ne conserve que les sites dans la discipline donnée.
+           
+        Si ``disicipline`` est None, ce filtre n'a aucun effet."""
+        if discipline is None:
+            return self
+        if not isinstance(discipline, Discipline):
+            discipline = Discipline.objects.get(pk=discipline)
+        return self.filter(Q(discipline=discipline) |
+                           Q(titre__icontains=discipline.nom) |
+                           Q(description__icontains=discipline.nom) |
+                           Q(mots_cles__icontains=discipline.nom))
 
-    def filter_pays(self, pays):
-        return self.get_query_set().filter_pays(pays)
+    def filter_region(self, region):
+        """Ne conserve que les sites dans la région donnée.
+           
+        Si ``region`` est None, ce filtre n'a aucun effet."""
+        if region is None:
+            return self
+        if not isinstance(region, Region):
+            region = Region.objects.get(pk=region)
+        return self.filter(Q(pays__region=region) |
+                           Q(titre__icontains=region.nom) |
+                           Q(description__icontains=region.nom) |
+                           Q(mots_cles__icontains=region.nom)).distinct()
 
 class Site(models.Model):
     """Fiche d'info d'un site web"""
@@ -70,7 +106,6 @@ class Site(models.Model):
 
     # Manager
     objects = SiteManager()
-    all_objects = models.Manager()
     
     def __unicode__(self):
         return "%s" % (self.titre)
index e45e9c9..d861e63 100644 (file)
@@ -2,18 +2,18 @@
 from django.shortcuts import render_to_response
 from django.template import Context, RequestContext
 from django.db.models import Q
-from forms import SiteSearchForm
+
 from models import Site
-from savoirs.lib.recherche import excerpt_function
+from forms import SiteSearchForm
 
 def index(request):
     search_form = SiteSearchForm(request.GET)
     sites = search_form.get_query_set()
+    search_regexp = search_form.get_search_regexp()
     nb_sites = sites.count()
-    excerpt = excerpt_function(Site.objects, search_form.cleaned_data['q'])
     return render_to_response("sites/index.html",
-                              dict(sites=sites, search_form=search_form,
-                                   excerpt=excerpt, nb_sites=nb_sites), 
+                              dict(sites=sites, search_form=search_form, 
+                                   search_regexp=search_regexp, nb_sites=nb_sites), 
                               context_instance = RequestContext(request))
             
 def retrieve(request, id):
index 322a71d..103094f 100644 (file)
@@ -1,9 +1,9 @@
-{% load sep %}
+{% load search %}
 
 <div class="resultatRecherche">
   <div class="la-date">{{ actualite.date|date:"d F Y" }}</div>
-  <a class="le-titre" href="{{ actualite.url }}">{{ actualite.titre|apply:excerpt }}</a>
-  <div class="resultatResume">{{ actualite.texte|apply:excerpt }}</div>
+  <a class="le-titre" href="{{ actualite.url }}">{{ actualite.titre|highlight:search_regexp }}</a>
+  <div class="resultatResume">{{ actualite.texte|highlight:search_regexp }}</div>
   {% if actualite.source %}
   <div><span class="lbl">Source:</span> {{ actualite.source.nom }}</div>
   {% endif %}
index 846f810..428d087 100644 (file)
@@ -1,7 +1,7 @@
-{% load sep %}
+{% load search %}
 
 <div class="resultatRecherche">
   <div class="la-date">{{ evenement.debut|date:"d/m/Y H\hi" }}</div>
-  <div><a href="{% url savoirs.views.evenement evenement.pk %}" class="le-titre">{{ evenement.titre|apply:excerpt }}</a></div>
-  <div class="le-resume">{{ evenement.description|apply:excerpt }}</div>
+  <div><a href="{% url savoirs.views.evenement evenement.pk %}" class="le-titre">{{ evenement.titre|highlight:search_regexp }}</a></div>
+  <div class="le-resume">{{ evenement.description|excerpt:search_regexp|highlight:search_regexp }}</div>
 </div>
index 3f0724b..8992f9a 100644 (file)
@@ -1,14 +1,20 @@
-{% load sep %}
+{% load search %}
 
 <div class="resultatRecherche">
-    <a class="le-titre" href="{% url savoirs.views.ressource_retrieve ressource.id %}">{{ ressource.title|apply:excerpt }}</a>
+    <a class="le-titre" href="{% url savoirs.views.ressource_retrieve ressource.id %}">{{ ressource.title|highlight:search_regexp }}</a>
     {% if ressource.creator %}
-    <div><span class="lbl">Auteur:</span> {{ ressource.creator|apply:excerpt }}</div>
+    <div><span class="lbl">Auteur:</span> {{ ressource.creator|highlight:search_regexp }}</div>
     {% endif %}
     {% if ressource.description %}
-    <div class="resultatResume"><span class="lbl">Description:</span> {{ ressource.description|apply:excerpt }}</div>
+    <div class="resultatResume"><span class="lbl">Description:</span> {{ ressource.description|excerpt:search_regexp|highlight:search_regexp }}</div>
     {% endif %}
     <div class="fiche"><span>Fiche: </span><a href="{% url savoirs.views.ressource_retrieve ressource.id %}">{% url savoirs.views.ressource_retrieve ressource.id %}</a></div>
     <div class="original"><span>Contenu original: </span><a target="_blank" href="{{ ressource.uri }}">{{ ressource.uri }}</a></div>
     <div class="provenance"><span>Provenance: </span><a target="_blank" href="{{ ressource.getServeurURL }}">{{ ressource.getServeurURL }}</a></div>
 </div>
+
+    {% comment %}
+    {% if user.is_authenticated %}
+    <a href="{{ r.admin_url}}" target="_blank">Modifier</a>
+    {% endif %}
+    {% endcomment %}
index 403d842..25f734c 100644 (file)
@@ -1,7 +1,7 @@
-{% load sep %}
+{% load search %}
 
 <div class="resultatRecherche">
-  <div><a class="le-titre" href="{% url sitotheque.views.retrieve site.id %}">{{ site.titre|apply:excerpt }}</a></div>
-  <div class="resultatResume">{{ site.description|apply:excerpt }}</div>
+  <div><a class="le-titre" href="{% url sitotheque.views.retrieve site.id %}">{{ site|highlight:search_regexp }}</a></div>
+  <div class="resultatResume">{{ site.description|excerpt:search_regexp|highlight:search_regexp }}</div>
   <div><span class="lbl">URL:</span> <a href="{{ site.url }}">{{ site.url }}</a></div>
 </div>
index b470269..6f5c9d1 100644 (file)
@@ -1,6 +1,6 @@
 [buildout]
 newest = false
-parts = django articles harvest sphinx_conf
+parts = django articles harvest
 find-links = http://pypi.auf.org/caldav/
     http://pypi.auf.org/auf_references_client/
     http://pypi.auf.org/auf_references_modeles/
@@ -27,7 +27,6 @@ eggs = auf_references_client
     datamaster_modeles
     django-roa
     django-admin-tools
-    django-sphinx
 
 #develop = src/caldav
 
@@ -45,8 +44,3 @@ template = harvest.in
 recipe = buildout_script
 template_dir = ${buildout:directory}/auf_savoirs_en_partage/scripts/
 template = import_chercheurs.in
-
-[sphinx_conf]
-recipe = buildout_script
-template_dir = ${buildout:directory}/auf_savoirs_en_partage/scripts/
-template = sphinx.conf.py.in