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)
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")
# -*- 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):
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):
# Manager
objects = ChercheurManager()
- all_objects = models.Manager()
def __unicode__(self):
return u"%s %s" % (self.personne.nom.upper(), self.personne.prenom.title())
# 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
# -*- 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
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)
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',
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
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):
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)
'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))
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."""
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."""
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'])
###
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
# 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ûüù]')
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
-
# -*- 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.
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')
db_table = u'discipline'
ordering = ["nom",]
-# Actualités
-
class SourceActualite(models.Model):
nom = models.CharField(max_length=255)
url = models.CharField(max_length=255)
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')
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'
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()
(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()))
regions = models.ManyToManyField(Region, blank=True, related_name="evenements", verbose_name='régions')
objects = EvenementManager()
- all_objects = models.Manager()
class Meta:
ordering = ['-debut']
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)
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):
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'
# -*- 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):
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 ""
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)
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
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,
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('"', '"') 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)
)
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):
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)
)
+++ /dev/null
-#!/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')
'savoirs',
'chercheurs',
'sitotheque',
- 'djangosphinx',
)
'authentification.CascadeBackend',
)
-CACHE_BACKEND = 'memcached://localhost:11211'
+CACHE_BACKEND = 'locmem://'
ROA_CUSTOM_ARGS = {'api-key': ROA_API_KEY}
CONTACT_EMAIL = 'contact-savoirsenpartage@auf.org'
-SPHINX_API_VERSION = 0x116
-SPHINX_PORT = 9312
-
from auf_references_client.settings import *
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:
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'])
# -*- 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'),
('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"""
# Manager
objects = SiteManager()
- all_objects = models.Manager()
def __unicode__(self):
return "%s" % (self.titre)
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):
-{% 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 %}
-{% 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>
-{% 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 %}
-{% 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>
[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/
datamaster_modeles
django-roa
django-admin-tools
- django-sphinx
#develop = src/caldav
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