Suppression de actif, et utilisation de statut
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / chercheurs / models.py
1 # -*- encoding: utf-8 -*-
2 import hashlib
3
4 from datamaster_modeles.models import *
5 from django.conf import settings
6 from django.contrib.auth.models import User
7 from django.core.urlresolvers import reverse as url
8 from django.db import models
9 from django.db.models import Q
10 from django.utils.encoding import smart_str
11 from django.utils.hashcompat import sha_constructor
12 from djangosphinx.models import SphinxSearch
13
14 from savoirs.models import Discipline, SEPManager, SEPSphinxQuerySet, SEPQuerySet, Search
15
16 GENRE_CHOICES = (('m', 'Homme'), ('f', 'Femme'))
17 class Personne(models.Model):
18 salutation = models.CharField(max_length=128, null=True, blank=True)
19 nom = models.CharField(max_length=255)
20 prenom = models.CharField(max_length=128, verbose_name='prénom')
21 courriel = models.EmailField(max_length=128, verbose_name="courriel")
22 afficher_courriel = models.BooleanField(default=True)
23 fonction = models.CharField(max_length=128, null=True, blank=True)
24 date_naissance = models.DateField(null=True, blank=True)
25 sousfonction = models.CharField(max_length=128, null=True, blank=True, verbose_name='sous-fonction')
26 telephone = models.CharField(max_length=32, null=True, blank=True, verbose_name='numéro de téléphone')
27 adresse_postale = models.TextField(blank=True)
28 genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
29 commentaire = models.TextField(verbose_name='commentaires', null=True, blank=True)
30 actif = models.BooleanField(editable=False, default=False)
31
32 def __unicode__(self):
33 return u"%s %s, %s" % (self.prenom, self.nom, self.courriel)
34
35 class Meta:
36 ordering = ["nom", "prenom"]
37
38 def save(self, *args, **kwargs):
39
40 old_instance = Personne.objects.get(pk=self.pk)
41 if self.courriel != old_instance.courriel:
42 try:
43 user = User.objects.get(email=old_instance.courriel)
44 user.email = self.courriel
45 user.save()
46 except User.DoesNotExist:
47 pass
48
49 super(Personne, self).save(*args, **kwargs)
50
51 @property
52 def civilite(self):
53 if self.genre == 'm':
54 return 'M.'
55 elif self.genre == 'f':
56 return 'Mme'
57 else:
58 return ''
59
60 def courriel_display(self):
61 return self.courriel.replace(u'@', u' (à) ')
62
63 class ChercheurQuerySet(SEPQuerySet):
64
65 def filter_groupe(self, groupe):
66 return self.filter(groupes=groupe)
67
68 def filter_pays(self, pays):
69 return self.filter(Q(etablissement__pays=pays) | Q(etablissement_autre_pays=pays))
70
71 def filter_region(self, region):
72 return self.filter(Q(etablissement__pays__region=region) | Q(etablissement_autre_pays__region=region))
73
74 def filter_nord_sud(self, nord_sud):
75 return self.filter(Q(etablissement__pays__nord_sud=nord_sud) | Q(etablissement_autre_pays__nord_sud=nord_sud))
76
77 def filter_genre(self, genre):
78 return self.filter(genre=genre)
79
80 def filter_statut(self, statut):
81 return self.filter(statut=statut)
82
83 def filter_expert(self):
84 return self.exclude(expertises=None)
85
86 def filter_date_modification(self, min=None, max=None):
87 return self._filter_date('date_modification', min=min, max=max)
88
89 def order_by_nom(self, direction=''):
90 return self.order_by(direction + 'nom', direction + 'prenom', '-date_modification')
91
92 def order_by_etablissement(self, direction=''):
93 return self.extra(select=dict(etablissement_nom='IFNULL(ref_etablissement.nom, chercheurs_chercheur.etablissement_autre_nom)'),
94 order_by=[direction + 'etablissement_nom', '-date_modification'])
95
96 def order_by_pays(self, direction=''):
97 return self.extra(select=dict(
98 pays_etablissement='''(SELECT nom FROM ref_pays
99 WHERE ref_pays.code = IFNULL(ref_etablissement.pays, chercheurs_chercheur.etablissement_autre_pays))'''
100 ), order_by=[direction + 'pays_etablissement', '-date_modification'])
101
102 class ChercheurSphinxQuerySet(SEPSphinxQuerySet):
103
104 def __init__(self, model=None):
105 return SEPSphinxQuerySet.__init__(self, model=model, index='savoirsenpartage_chercheurs',
106 weights=dict(nom=2, prenom=2))
107
108 def filter_region(self, region):
109 return self.filter(region_id=region.id)
110
111 def filter_groupe(self, groupe):
112 return self.filter(groupe_ids=groupe.id)
113
114 def filter_pays(self, pays):
115 return self.filter(pays_id=pays.id)
116
117 NORD_SUD_CODES = {'Nord': 1, 'Sud': 2}
118 def filter_nord_sud(self, nord_sud):
119 return self.filter(nord_sud=self.NORD_SUD_CODES[nord_sud])
120
121 GENRE_CODES = dict([(k, i+1) for i, (k, v) in enumerate(GENRE_CHOICES)])
122 def filter_genre(self, genre):
123 return self.filter(genre=self.GENRE_CODES[genre])
124
125 STATUT_CODES = {'enseignant': 1, 'etudiant': 2, 'independant': 3}
126 def filter_statut(self, statut):
127 return self.filter(statut=self.STATUT_CODES[statut])
128
129 def filter_expert(self):
130 return self.filter(expert=True)
131
132 def filter_date_modification(self, min=None, max=None):
133 return self._filter_date('date_modification', min=min, max=max)
134
135 def order_by_nom(self, direction=''):
136 return self.order_by(direction + 'nom_complet', '-date_modification')
137
138 def order_by_etablissement(self, direction=''):
139 return self.order_by(direction + 'etablissement_attr', '-date_modification')
140
141 def order_by_pays(self, direction=''):
142 return self.order_by(direction + 'pays_attr', '-date_modification')
143
144 class ChercheurManager(SEPManager):
145
146 def get_query_set(self):
147 return ChercheurQuerySet(self.model).filter(actif=True)
148
149 def get_sphinx_query_set(self):
150 return ChercheurSphinxQuerySet(self.model).order_by('-date_modification')
151
152 def filter_region(self, region):
153 """Le filtrage de chercheurs par région n'est pas une recherche texte."""
154 return self.get_query_set().filter_region(region)
155
156 def filter_groupe(self, groupe):
157 return self.get_query_set().filter_groupe(groupe)
158
159 def filter_pays(self, pays):
160 return self.get_query_set().filter_pays(pays)
161
162 def filter_nord_sud(self, nord_sud):
163 return self.get_query_set().filter_nord_sud(nord_sud)
164
165 def filter_genre(self, genre):
166 return self.get_query_set().filter_genre(genre=genre)
167
168 def filter_statut(self, statut):
169 return self.get_query_set().filter_statut(statut)
170
171 def filter_expert(self):
172 return self.get_query_set().filter_expert()
173
174 def filter_date_modification(self, min=None, max=None):
175 return self.get_query_set().filter_date_modification(min=min, max=max)
176
177 def order_by_nom(self, direction=''):
178 return self.get_query_set().order_by_nom(self, direction=direction)
179
180 def order_by_etablissement(self, direction=''):
181 return self.get_query_set().order_by_etablissement(self, direction=direction)
182
183 def order_by_pays(self, direction=''):
184 return self.get_query_set().order_by_pays(self, direction=direction)
185
186 STATUT_CHOICES = (
187 ('enseignant', 'Enseignant-chercheur dans un établissement'),
188 ('etudiant', 'Étudiant-chercheur doctorant'),
189 ('independant', 'Chercheur indépendant docteur')
190 )
191
192 class Chercheur(Personne):
193 RESEAU_INSTITUTIONNEL_CHOICES = (
194 ('AFELSH', 'Association des facultés ou établissements de lettres et sciences humaines des universités d’expression française (AFELSH)'),
195 ('CIDEGEF', 'Conférence internationale des dirigeants des institutions d’enseignement supérieur et de recherche de gestion d’expression française (CIDEGEF)'),
196 ('RIFEFF', 'Réseau international francophone des établissements de formation de formateurs (RIFEFF)'),
197 ('CIDMEF', 'Conférence internationale des doyens des facultés de médecine d’expression française (CIDMEF)'),
198 ('CIDCDF', 'Conférence internationale des doyens des facultés de chirurgie dentaire d’expression totalement ou partiellement française (CIDCDF)'),
199 ('CIFDUF', 'Conférence internationale des facultés de droit ayant en commun l’usage du français (CIFDUF)'),
200 ('CIRUISEF', 'Conférence internationale des responsables des universités et institutions à dominante scientifique et technique d’expression française (CIRUISEF)'),
201 ('Theophraste', 'Réseau Théophraste (Réseau de centres francophones de formation au journalisme)'),
202 ('CIDPHARMEF', 'Conférence internationale des doyens des facultés de pharmacie d’expression française (CIDPHARMEF)'),
203 ('CIDEFA', 'Conférence internationale des directeurs et doyens des établissements supérieurs d’expression française des sciences de l’agriculture et de l’alimentation (CIDEFA)'),
204 ('CITEF', 'Conférence internationale des formations d’ingénieurs et techniciens d’expression française (CITEF)'),
205 ('APERAU', 'Association pour la promotion de l’enseignement et de la recherche en aménagement et urbanisme (APERAU)'),
206 )
207 INSTANCE_AUF_CHOICES = (
208 ('CASSOC', 'Conseil associatif'),
209 ('CA', "Conseil d'administration"),
210 ('CS', 'Conseil scientifique'),
211 ('CRE', "Commission régionale d'experts"),
212 ('CR', 'Conférence des recteurs'),
213 ('CNO', "Conseil national d'orientation")
214 )
215
216 nationalite = models.ForeignKey(Pays, null = True, db_column='nationalite', to_field='code',
217 verbose_name = 'nationalité', related_name='nationalite')
218 statut = models.CharField(max_length=36, choices=STATUT_CHOICES)
219 diplome = models.CharField(max_length=255, null=True, verbose_name = 'diplôme le plus élevé')
220 etablissement = models.ForeignKey(Etablissement, db_column='etablissement', null=True, blank=True)
221 etablissement_autre_nom = models.CharField(max_length=255, null=True, blank=True, verbose_name = 'autre établissement')
222 etablissement_autre_pays = models.ForeignKey(Pays, null = True, blank=True, db_column='etablissement_autre_pays',
223 to_field='code', related_name='etablissement_autre_pays',
224 verbose_name = "pays de l'établissement")
225 attestation = models.BooleanField()
226
227 #Domaine
228 thematique = models.ForeignKey(Thematique, db_column='thematique', blank=True, null=True, verbose_name='thematique')
229 mots_cles = models.CharField(max_length=255, null=True, verbose_name='mots-clés')
230 discipline = models.ForeignKey(Discipline, db_column='discipline', null=True, verbose_name='Discipline')
231 theme_recherche = models.TextField(null=True, blank=True, verbose_name='thèmes de recherche')
232 groupe_recherche = models.CharField(max_length=255, blank=True, verbose_name='groupe de recherche')
233 url_site_web = models.URLField(max_length=255, null=True, blank=True,
234 verbose_name='adresse site Internet', verify_exists=False)
235 url_blog = models.URLField(max_length=255, null=True, blank=True, verbose_name='blog',
236 verify_exists=False)
237 url_reseau_social = models.URLField(
238 max_length=255, null=True, blank=True, verbose_name='Réseau social',
239 verify_exists=False,
240 help_text=u"Vous pouvez indiquer ici l'adresse de votre page personnelle dans votre réseau social préféré (e.g. Facebook, LinkedIn, Twitter, Identica, ...)"
241 )
242
243 groupes = models.ManyToManyField('Groupe', through='ChercheurGroupe', related_name='membres', blank=True, verbose_name='Domaines de recherche')
244
245 # Activités en francophonie
246 membre_instance_auf = models.NullBooleanField(verbose_name="est ou a déjà été membre d'une instance de l'AUF")
247 membre_instance_auf_nom = models.CharField(max_length=10, blank=True, choices=INSTANCE_AUF_CHOICES, verbose_name="instance")
248 membre_instance_auf_fonction = models.CharField(max_length=255, blank=True, verbose_name="fonction")
249 membre_instance_auf_dates = models.CharField(max_length=255, blank=True, verbose_name="dates")
250 expert_oif = models.NullBooleanField(verbose_name="a été sollicité par l'OIF")
251 expert_oif_details = models.CharField(max_length=255, blank=True, verbose_name="détails")
252 expert_oif_dates = models.CharField(max_length=255, blank=True, verbose_name="dates")
253 membre_association_francophone = models.NullBooleanField(verbose_name="est membre d'une association francophone")
254 membre_association_francophone_details = models.CharField(max_length=255, blank=True, verbose_name="nom de l'association")
255 membre_reseau_institutionnel = models.NullBooleanField(
256 verbose_name="est membre des instances d'un réseau institutionnel de l'AUF"
257 )
258 membre_reseau_institutionnel_nom = models.CharField(
259 max_length=15, choices=RESEAU_INSTITUTIONNEL_CHOICES, blank=True,
260 verbose_name="réseau institutionnel"
261 )
262 membre_reseau_institutionnel_fonction = models.CharField(
263 max_length=255, blank=True, verbose_name="fonction"
264 )
265 membre_reseau_institutionnel_dates = models.CharField(
266 max_length=255, blank=True, verbose_name="dates"
267 )
268
269 # Expertises
270 expertises_auf = models.NullBooleanField(verbose_name="est disposé à réaliser des expertises pour l'AUF")
271
272 #meta
273 date_creation = models.DateField(auto_now_add=True, db_column='date_creation')
274 date_modification = models.DateField(auto_now=True, db_column='date_modification')
275
276 # Manager
277 objects = ChercheurManager()
278 all_objects = models.Manager()
279
280 def __unicode__(self):
281 return u"%s %s" % (self.nom.upper(), self.prenom.title())
282
283 def statut_display(self):
284 for s in STATUT_CHOICES:
285 if self.statut == s[0]:
286 return s[1]
287 return "-"
288
289 @property
290 def etablissement_display(self):
291 return (self.nom_etablissement or '') + (', ' + self.pays.nom if self.pays else '')
292
293 @property
294 def pays(self):
295 return self.etablissement.pays if self.etablissement else self.etablissement_autre_pays
296
297 @property
298 def nom_etablissement(self):
299 return self.etablissement.nom if self.etablissement else self.etablissement_autre_nom
300
301 @property
302 def region(self):
303 return self.pays.region
304
305 @property
306 def domaines_recherche(self):
307 return self.groupes.filter(groupe_chercheur=False)
308
309 @property
310 def groupes_chercheur(self):
311 return self.groupes.filter(groupe_chercheur=True)
312
313 def save(self):
314 """Si on a donné un établissement membre, on laisse tomber l'autre établissement."""
315 if self.etablissement:
316 self.etablissement_autre_nom = None
317 self.etablissement_autre_pays = None
318 super(Chercheur, self).save()
319
320 def activation_token(self):
321 return sha_constructor(settings.SECRET_KEY + unicode(self.id)).hexdigest()[::2]
322
323 def get_absolute_url(self):
324 return url('chercheur', kwargs={'id': self.id})
325
326 class ChercheurVoir(Chercheur):
327
328 class Meta:
329 proxy = True
330 verbose_name = '(visualisation) chercheur'
331 verbose_name_plural = '(visualisation) chercheur'
332
333 class Publication(models.Model):
334 chercheur = models.ForeignKey(Chercheur, related_name='publications')
335 auteurs = models.CharField(max_length=255, blank=True, verbose_name='auteur(s)')
336 titre = models.CharField(max_length=255, null=True, blank=True, verbose_name='titre')
337 revue = models.CharField(max_length=255, null=True, blank=True, verbose_name='revue')
338 annee = models.IntegerField(null=True, blank=True, verbose_name='année de publication')
339 editeur = models.CharField(max_length=255, null=True, blank=True, verbose_name='éditeur')
340 lieu_edition = models.CharField(max_length=255, null=True, blank=True, verbose_name="lieu d'édition")
341 nb_pages = models.CharField(max_length=255, null=True, blank=True, verbose_name='nombre de pages')
342 url = models.URLField(max_length=255, null=True, blank=True, verbose_name='lien vers la publication', verify_exists=False)
343 #Migration des publications depuis l'ancien repertoire de chercheurs
344 publication_affichage = models.TextField(verbose_name='publication', null=True, blank=True)
345 actif = models.BooleanField(editable=False)
346
347 def __unicode__(self):
348 return self.titre or '(Aucun)'
349
350 def save(self):
351 if self.publication_affichage and (self.auteurs or self.titre or
352 self.revue or self.annee or
353 self.editeur or self.lieu_edition
354 or self.nb_pages or self.url):
355 self.publication_affichage = ''
356 super(Publication, self).save()
357
358 class These(models.Model):
359 chercheur = models.OneToOneField(Chercheur, primary_key=True)
360 titre = models.CharField(max_length=255, verbose_name='Titre')
361 annee = models.IntegerField(verbose_name='Année de soutenance (réalisée ou prévue)')
362 directeur = models.CharField(max_length=255, verbose_name='Directeur')
363 etablissement = models.CharField(max_length=255, verbose_name='Établissement de soutenance')
364 nb_pages = models.IntegerField(verbose_name='Nombre de pages', blank=True, null=True)
365 url = models.URLField(max_length=255, verbose_name='Lien vers la publication', blank=True, verify_exists=False)
366
367 def __unicode__(self):
368 return self.titre
369
370 class Expertise(models.Model):
371 id = models.AutoField(primary_key=True, db_column='id')
372 chercheur = models.ForeignKey(Chercheur, related_name='expertises')
373 nom = models.CharField(max_length=255, verbose_name = "Objet de l'expertise")
374 date = models.CharField(max_length=255, blank=True)
375 lieu = models.CharField(max_length=255, null=True, blank=True, verbose_name = "Lieu de l'expertise")
376 organisme_demandeur = models.CharField(max_length=255, null=True, blank=True, verbose_name = 'Organisme demandeur')
377 organisme_demandeur_visible = models.BooleanField(verbose_name="Afficher l'organisme demandeur")
378 actif = models.BooleanField(editable = False, db_column='actif')
379
380 def __unicode__(self):
381 return u"%s" % (self.nom)
382
383 class GroupeManager(models.Manager):
384 def search(self, text):
385 return self.get_query_set().filter(nom__icontains=text)
386
387 class GroupeChercheurManager(GroupeManager):
388 def get_query_set(self):
389 return super(GroupeChercheurManager, self).get_query_set().filter(groupe_chercheur=True)
390
391 class DomaineRechercheManager(GroupeManager):
392 def get_query_set(self):
393 return super(DomaineRechercheManager, self).get_query_set().filter(groupe_chercheur=False)
394
395 class Groupe(models.Model):
396 id = models.AutoField(primary_key=True, db_column='id')
397 nom = models.CharField(max_length=255, db_column='nom')
398 url = models.URLField(max_length=255, null=True, blank=True,
399 verbose_name='Site web')
400 liste_diffusion = models.URLField(max_length=255, null=True, blank=True,
401 verbose_name='Liste de diffusion')
402 bulletin = models.URLField(max_length=255, null=True, blank=True,
403 verbose_name='Bulletin')
404 actif = models.BooleanField(editable = False, db_column='actif')
405 groupe_chercheur = models.BooleanField(default=False, editable=False, verbose_name='Groupe de chercheur')
406
407 responsables = models.ManyToManyField(User, related_name='responsable_groupe', verbose_name='responsables', blank=True)
408
409 recherches = models.ManyToManyField(Search, related_name='recherche_groupe', verbose_name='recherches prédéfinies', blank=True)
410
411 page_accueil = models.TextField(null=True, blank=True)
412
413 objects = GroupeManager()
414 groupe_chercheur_objects = GroupeChercheurManager()
415 domaine_recherche_objects = DomaineRechercheManager()
416
417 class Meta:
418 verbose_name = 'domaine de recherche'
419 verbose_name_plural = 'domaines de recherche'
420
421 def __unicode__(self):
422 return u"%s" % (self.nom)
423
424 def get_absolute_url(self):
425 return url('groupe_retrieve', kwargs={'id': self.id})
426
427
428 class GroupeChercheur(Groupe):
429 objects = GroupeChercheurManager()
430
431 class Meta:
432 proxy = True
433 verbose_name = 'groupe de chercheurs'
434 verbose_name_plural = 'groupes de chercheurs'
435
436 def save(self, *args, **kwargs):
437 self.groupe_chercheur = True
438 super(GroupeChercheur, self).save(*args, **kwargs)
439
440 class DomaineRecherche(Groupe):
441 objects = DomaineRechercheManager()
442
443 class Meta:
444 proxy = True
445 verbose_name = 'domaine de recherche'
446 verbose_name_plural = 'domaines de recherche'
447
448 def save(self, *args, **kwargs):
449 self.groupe_chercheur = False
450 super(DomaineRecherche, self).save(*args, **kwargs)
451
452 class ChercheurGroupe(models.Model):
453 CG_STATUT_CHOICES = (
454 ('nouveau', 'Nouveau'),
455 ('refuse', 'Refusé'),
456 ('accepte', 'Accepté'),
457 ('resilie', 'Résilié'),
458 ('exclus', 'Exclus'),
459 )
460
461 id = models.AutoField(primary_key=True, db_column='id')
462 chercheur = models.ForeignKey('Chercheur', db_column='chercheur')
463 groupe = models.ForeignKey('Groupe', db_column='groupe', related_name="membership")
464 date_inscription = models.DateField(auto_now_add=True)
465 date_modification = models.DateField(auto_now=True)
466 statut = models.CharField(max_length=100, choices=CG_STATUT_CHOICES, default='nouveau')
467
468 class Meta:
469 verbose_name = 'adhésion aux groupes'
470 verbose_name_plural = 'adhésions aux groupes'
471 ordering = ['chercheur']
472
473 def __unicode__(self):
474 return u"%s - %s" % (self.chercheur, self.groupe)
475
476 class ChercheurSearch(Search):
477 nom_chercheur = models.CharField(max_length=100, blank=True, verbose_name='nom')
478 domaine = models.ForeignKey(DomaineRecherche, blank=True, null=True, verbose_name='domaine de recherche')
479 groupe_chercheur = models.ForeignKey(GroupeChercheur, blank=True, null=True, verbose_name='groupe de chercheurs')
480 groupe_recherche = models.CharField(max_length=100, blank=True, null=True,
481 verbose_name='groupe de recherche',
482 help_text='ou Laboratoire, ou Groupement inter-universitaire')
483 statut = models.CharField(max_length=100, blank=True, choices=STATUT_CHOICES + (('expert', 'Expert'),))
484 pays = models.ForeignKey(Pays, blank=True, null=True)
485 nord_sud = models.CharField(max_length=4, blank=True, choices=(('Nord', 'Nord'), ('Sud', 'Sud')),
486 verbose_name='Nord/Sud',
487 help_text="Distinction d'ordre géopolitique et économique, non géographique, qui conditionne souvent l'attribution de soutiens par les agences internationales: on entend par Nord les pays développés, par Sud les pays en développement (pays les moins avancés, pays émergents et pays à économies en transition)")
488 activites_francophonie = models.CharField(
489 max_length=25, blank=True, verbose_name='activités en Francophonie',
490 choices=(('instance_auf', "Membre d'une instance de l'AUF"),
491 ('expert_oif', "Sollicité par l'OIF"),
492 ('association_francophone', "Membre d'une association ou d'une société savante francophone"),
493 ('reseau_institutionnel', "Membre des instances d'un réseau institutionnel de l'AUF"))
494 )
495 genre = models.CharField(max_length=1, blank=True, choices=GENRE_CHOICES)
496
497 class Meta:
498 verbose_name = 'recherche de chercheurs'
499 verbose_name_plural = 'recherches de chercheurs'
500
501 def run(self, min_date=None, max_date=None):
502 results = Chercheur.objects
503 if self.q:
504 results = results.search(self.q)
505 if self.nom_chercheur:
506 results = results.add_to_query('@(nom,prenom) ' + self.nom_chercheur)
507 if self.groupe_recherche:
508 results = results.add_to_query('@groupe_recherche ' + self.groupe_recherche)
509 if self.discipline:
510 results = results.filter_discipline(self.discipline)
511 if self.region:
512 results = results.filter_region(self.region)
513 if self.statut:
514 if self.statut == "expert":
515 results = results.filter_expert()
516 else:
517 results = results.filter_statut(self.statut)
518 if self.domaine:
519 results = results.filter_groupe(self.domaine)
520 if self.groupe_chercheur:
521 results = results.filter_groupe(self.groupe_chercheur)
522 if self.pays:
523 results = results.filter_pays(self.pays)
524 if self.nord_sud:
525 results = results.filter_nord_sud(self.nord_sud)
526 if self.genre:
527 results = results.filter_genre(self.genre)
528 if self.activites_francophonie == 'instance_auf':
529 results = results.filter(membre_instance_auf=True)
530 elif self.activites_francophonie == 'expert_oif':
531 results = results.filter(expert_oif=True)
532 elif self.activites_francophonie == 'association_francophone':
533 results = results.filter(membre_association_francophone=True)
534 elif self.activites_francophonie == 'reseau_institutionnel':
535 results = results.filter(membre_reseau_institutionnel=True)
536 if min_date:
537 results = results.filter_date_modification(min=min_date)
538 if max_date:
539 results = results.filter_date_modification(max=max_date)
540 return results.all()
541
542 def url(self):
543 qs = self.query_string()
544 return url('chercheurs') + ('?' + qs if qs else '')
545
546 def rss_url(self):
547 qs = self.query_string()
548 return url('rss_chercheurs') + ('?' + qs if qs else '')
549
550 def get_email_alert_content(self, results):
551 content = ''
552 for chercheur in results:
553 content += u'- [%s %s](%s%s) \n' % (chercheur.nom.upper(),
554 chercheur.prenom,
555 settings.SITE_ROOT_URL,
556 chercheur.get_absolute_url())
557 content += u' %s\n\n' % chercheur.etablissement_display
558 return content
559
560 class GroupeSearch(Search):
561
562 class Meta:
563 verbose_name = 'recherche de groupe'
564 verbose_name_plural = 'recherches de groupes'
565
566 def run(self):
567 results = Groupe.objects
568 if self.q:
569 results = results.search(self.q)
570 return results.all()
571
572 #def url(self):
573 # qs = self.query_string()
574 # return url('groupes') + ('?' + qs if qs else '')
575
576 #def rss_url(self):
577 # qs = self.query_string()
578 # return url('rss_groupes') + ('?' + qs if qs else '')
579
580 class Message(models.Model):
581
582 chercheur = models.ForeignKey('Chercheur', db_column='chercheur')
583 groupe = models.ForeignKey('Groupe', db_column='groupe')
584 titre = models.CharField(max_length=255)
585 contenu = models.TextField()
586
587 date_creation = models.DateTimeField(auto_now_add=True, db_column='date_creation')
588
589 class Meta:
590 ordering = ['-date_creation']
591
592 def __unicode__(self):
593 return u"%s - %s" % (self.chercheur, self.titre)
594
595 def get_absolute_url(self):
596 return url('groupe_messages', kwargs={'id': self.groupe.id})
597