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