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