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