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