1 # -*- encoding: utf-8 -*-
3 from django
import forms
4 from django
.contrib
.auth
.forms
import AuthenticationForm
as DjangoAuthenticationForm
, SetPasswordForm
as DjangoSetPasswordForm
5 from django
.db
.models
import Q
6 from django
.forms
.models
import inlineformset_factory
7 from itertools
import chain
10 OUI_NON_CHOICES
= ((True, 'Oui'), (False, 'Non'))
12 class ChercheurForm(forms
.ModelForm
):
13 """Formulaire d'édition d'un chercheur."""
14 genre
= forms
.ChoiceField(widget
=forms
.RadioSelect(), choices
=GENRE_CHOICES
)
15 afficher_courriel
= forms
.ChoiceField(
16 label
="Afficher mon courriel publiquement sur ce site",
17 choices
=OUI_NON_CHOICES
, widget
=forms
.RadioSelect()
19 membre_instance_auf
= forms
.ChoiceField(
20 label
="Êtes-vous (ou avez-vous déjà été) membre d'une instance de l'AUF?",
21 choices
=OUI_NON_CHOICES
, widget
=forms
.RadioSelect()
23 membre_instance_auf_nom
= forms
.ChoiceField(
24 choices
= (('', '---------'),) + Chercheur
.INSTANCE_AUF_CHOICES
,
25 label
="Préciser laquelle", required
=False
27 membre_instance_auf_fonction
= forms
.CharField(label
="Préciser votre fonction", required
=False)
28 membre_instance_auf_dates
= forms
.CharField(label
="Préciser les dates", required
=False)
29 expert_oif
= forms
.ChoiceField(label
="Avez-vous déjà été sollicité par l'OIF?", choices
=OUI_NON_CHOICES
, widget
=forms
.RadioSelect())
30 expert_oif_details
= forms
.CharField(label
="Préciser à quel titre", required
=False,
31 help_text
="Fonction dans l'organisation, participation à une étude ou à une action, etc.")
32 expert_oif_dates
= forms
.CharField(label
="Préciser les dates", required
=False)
33 membre_association_francophone
= forms
.ChoiceField(
34 label
="Êtes-vous membre d'une association ou d'une société savante francophone?",
35 help_text
="e.g. FIPF, Collège international de philosophie, AISLF, etc.",
36 choices
=OUI_NON_CHOICES
, widget
=forms
.RadioSelect()
38 membre_association_francophone_details
= forms
.CharField(label
="Préciser laquelle", required
=False)
39 membre_reseau_institutionnel
= forms
.ChoiceField(
40 label
="Êtes-vous (ou avez-vous déjà été) membre des instances d'un réseau institutionnel de l'AUF?",
41 choices
=OUI_NON_CHOICES
, widget
=forms
.RadioSelect()
43 membre_reseau_institutionnel_nom
= forms
.ChoiceField(
44 label
="Préciser le réseau institutionnel",
45 choices
=(('', '---------'),) + Chercheur
.RESEAU_INSTITUTIONNEL_CHOICES
,
48 membre_reseau_institutionnel_fonction
= forms
.CharField(required
=False, label
="Préciser votre fonction")
49 membre_reseau_institutionnel_dates
= forms
.CharField(required
=False, label
="Préciser les dates")
51 pays_etablissement
= forms
.ModelChoiceField(label
="Pays de l'établissement", queryset
=Pays
.objects
.all(), to_field_name
='code', required
=True)
52 etablissement
= forms
.CharField(
53 label
="Nom de l'établissement", required
=True,
54 help_text
="Après avoir sélectionné un pays, une liste d'établissement apparaît dès la saisie partielle du nom de l'établissement."
57 pas_de_sollicitation_expertises
= forms
.BooleanField(
59 label
="Je ne souhaite pas être sollicité par l'AUF pour des missions d'expertise"
62 theme_recherche
= forms
.CharField(
63 max_length
=1000, label
='Thèmes de recherche', help_text
='1000 signes maximum',
64 error_messages
=dict(max_length
="Veuillez entrer au maximum %(limit_value)d signes (vous en avez entré %(show_value)d)."),
65 widget
=forms
.Textarea()
67 attestation
= forms
.BooleanField(
69 label
="J'atteste sur l'honneur l'exactitude des renseignements fournis sur le formulaire d'inscription et j'accepte leur publication en ligne."
71 discipline
= forms
.ModelChoiceField(
72 label
="Discipline", required
=True,
73 queryset
=Discipline
.objects
.all(),
74 help_text
="La liste des disciplines procède d'un choix fait par le conseil scientifique de l'AUF."
76 equipe_recherche
= forms
.CharField(
77 max_length
=255, label
='Équipe de recherche', required
=False,
78 help_text
="Indiquer l'appartenance à une équipe de recherche universitaire ou laboratoire ou groupement inter-universitaire"
80 url_site_web
= forms
.URLField(
81 label
='Adresse site Internet', required
=False,
82 help_text
="Si vous le souhaitez, vous pouvez y indiquer le lien qui renvoie vers une page personnelle (sur le site de votre établissement par exemple) plus complète."
87 fields
= ('nom', 'prenom', 'genre', 'courriel', 'afficher_courriel', 'adresse_postale', 'telephone',
89 'discipline', 'theme_recherche', 'equipe_recherche',
90 'mots_cles', 'url_site_web', 'url_blog',
91 'url_reseau_social', 'attestation', 'membre_instance_auf',
92 'membre_instance_auf_nom', 'membre_instance_auf_fonction',
93 'membre_instance_auf_dates', 'expert_oif',
94 'expert_oif_details', 'expert_oif_dates',
95 'membre_association_francophone',
96 'membre_association_francophone_details',
97 'membre_reseau_institutionnel',
98 'membre_reseau_institutionnel_nom',
99 'membre_reseau_institutionnel_fonction',
100 'membre_reseau_institutionnel_dates')
102 def __init__(self
, data
=None, prefix
=None, instance
=None):
103 if instance
is not None:
105 if instance
.etablissement
:
106 initial
['etablissement'] = instance
.etablissement
.nom
107 initial
['pays_etablissement'] = instance
.etablissement
.pays
109 initial
['etablissement'] = instance
.etablissement_autre_nom
110 initial
['pays_etablissement'] = instance
.etablissement_autre_pays
111 initial
['pas_de_sollicitation_expertises'] = not instance
.expertises_auf
114 super(ChercheurForm
, self
).__init__(data
=data
, prefix
=prefix
, instance
=instance
, initial
=initial
)
117 nom_etablissement
= self
.cleaned_data
['etablissement']
118 pays_etablissement
= self
.cleaned_data
['pays_etablissement']
119 etablissements
= Etablissement
.objects
.filter(nom
=nom_etablissement
, pays
=pays_etablissement
, actif
=True)
120 if etablissements
.count() > 0:
121 self
.instance
.etablissement
= etablissements
[0]
122 self
.instance
.etablissement_autre
= ''
123 self
.instance
.etablissement_autre_pays
= None
125 self
.instance
.etablissement
= None
126 self
.instance
.etablissement_autre_nom
= nom_etablissement
127 self
.instance
.etablissement_autre_pays
= pays_etablissement
128 self
.instance
.expertises_auf
= not self
.cleaned_data
['pas_de_sollicitation_expertises']
129 super(ChercheurForm
, self
).save()
131 def clean_courriel(self
):
132 """On veut s'assurer qu'il n'y ait pas d'autre utilisateur actif
133 avec le même courriel."""
134 courriel
= self
.cleaned_data
['courriel']
135 existing
= Chercheur
.objects
.filter(courriel
=courriel
, actif
=True)
136 if self
.instance
and self
.instance
.id:
137 existing
= existing
.exclude(id=self
.instance
.id)
141 user
= User
.objects
.filter(is_active
=True, email
=courriel
)
143 raise forms
.ValidationError('Il existe déjà une fiche pour cette adresse électronique')
146 raise forms
.ValidationError('Il existe déjà une fiche pour cette adresse électronique')
149 def clean_afficher_courriel(self
):
150 return self
.cleaned_data
['afficher_courriel'] == 'True'
152 def clean_membre_instance_auf(self
):
153 return self
.cleaned_data
['membre_instance_auf'] == 'True'
155 def clean_membre_instance_auf_nom(self
):
156 membre
= self
.cleaned_data
.get('membre_instance_auf')
157 nom
= self
.cleaned_data
.get('membre_instance_auf_nom')
158 if membre
and not nom
:
159 raise forms
.ValidationError('Veuillez préciser')
162 def clean_membre_instance_auf_fonction(self
):
163 membre
= self
.cleaned_data
.get('membre_instance_auf')
164 fonction
= self
.cleaned_data
.get('membre_instance_auf_fonction')
165 if membre
and not fonction
:
166 raise forms
.ValidationError('Veuillez préciser')
169 def clean_membre_instance_auf_dates(self
):
170 membre
= self
.cleaned_data
.get('membre_instance_auf')
171 dates
= self
.cleaned_data
.get('membre_instance_auf_dates')
172 if membre
and not dates
:
173 raise forms
.ValidationError('Veuillez préciser les dates')
176 def clean_expert_oif(self
):
177 return self
.cleaned_data
['expert_oif'] == 'True'
179 def clean_expert_oif_details(self
):
180 expert
= self
.cleaned_data
.get('expert_oif')
181 details
= self
.cleaned_data
.get('expert_oif_details')
182 if expert
and not details
:
183 raise forms
.ValidationError('Veuillez préciser')
186 def clean_expert_oif_dates(self
):
187 expert
= self
.cleaned_data
.get('expert_oif')
188 dates
= self
.cleaned_data
.get('expert_oif_dates')
189 if expert
and not dates
:
190 raise forms
.ValidationError('Veuillez préciser les dates')
193 def clean_membre_association_francophone(self
):
194 return self
.cleaned_data
['membre_association_francophone'] == 'True'
196 def clean_membre_association_francophone_details(self
):
197 membre
= self
.cleaned_data
.get('membre_association_francophone')
198 details
= self
.cleaned_data
.get('membre_association_francophone_details')
199 if membre
and not details
:
200 raise forms
.ValidationError('Veuillez préciser')
203 def clean_membre_reseau_institutionnel(self
):
204 return self
.cleaned_data
['membre_reseau_institutionnel'] == 'True'
206 def clean_membre_reseau_institutionnel_nom(self
):
207 membre
= self
.cleaned_data
.get('membre_reseau_institutionnel')
208 nom
= self
.cleaned_data
.get('membre_reseau_institutionnel_nom')
209 if membre
and not nom
:
210 raise forms
.ValidationError('Veuillez préciser')
213 def clean_membre_reseau_institutionnel_fonction(self
):
214 membre
= self
.cleaned_data
.get('membre_reseau_institutionnel')
215 fonction
= self
.cleaned_data
.get('membre_reseau_institutionnel_fonction')
216 if membre
and not fonction
:
217 raise forms
.ValidationError('Veuillez préciser')
220 def clean_membre_reseau_institutionnel_dates(self
):
221 membre
= self
.cleaned_data
.get('membre_reseau_institutionnel')
222 dates
= self
.cleaned_data
.get('membre_reseau_institutionnel_dates')
223 if membre
and not dates
:
224 raise forms
.ValidationError('Veuillez préciser les dates')
227 class ChercheurInscriptionForm(ChercheurForm
):
229 class Meta(ChercheurForm
.Meta
):
231 #fields = ChercheurForm.Meta.fields + ('courriel',)
233 class GroupesForm(forms
.Form
):
234 """Formulaire qui associe des domaines de recherche et groupe de chercheur à un chercheur."""
235 domaines_recherche
= forms
.ModelMultipleChoiceField(
236 queryset
=Groupe
.domaine_recherche_objects
.all(),
237 label
='Domaines de recherche', required
=False,
238 help_text
="Ce champ est proposé à titre d'indication complémentaire, mais il n'est pas obligatoire. Maintenez appuyé « Ctrl », ou « Commande (touche pomme) » sur un Mac, pour en sélectionner plusieurs."
241 #groupes_chercheur = forms.ModelMultipleChoiceField(
242 # queryset=Groupe.groupe_chercheur_objects.all(),
243 # label='Communautés de chercheurs', required=False,
244 # help_text="Adhérez à un ou plusieurs communautés de chercheurs. Votre demande doit être approuvée par le gestionnaire de communauté.<br><br>Ce champ est proposé à titre d'indication complémentaire, mais il n'est pas obligatoire. Maintenez appuyé « Ctrl », ou « Commande (touche pomme) » sur un Mac, pour en sélectionner plusieurs."
247 def __init__(self
, data
=None, prefix
=None, chercheur
=None):
248 self
.chercheur
= chercheur
251 initial
['domaines_recherche'] = chercheur
.domaines_recherche
.values_list('id', flat
=True)
252 #initial['groupes_chercheur'] = chercheur.groupes_chercheur.values_list('id', flat=True)
253 super(GroupesForm
, self
).__init__(data
=data
, prefix
=prefix
, initial
=initial
)
257 domaines_recherche
= self
.cleaned_data
['domaines_recherche']
258 AdhesionGroupe
.objects
.filter(chercheur
=self
.chercheur
).exclude(groupe__groupe_chercheur
=True).exclude(groupe__in
=domaines_recherche
).delete()
259 for dr
in domaines_recherche
:
260 adhesion
, created
= AdhesionGroupe
.objects
.get_or_create(chercheur
=self
.chercheur
, groupe
=dr
)
265 #groupes_chercheur = self.cleaned_data['groupes_chercheur']
266 #AdhesionGroupe.objects.filter(chercheur=self.chercheur).exclude(groupe__groupe_chercheur=False).exclude(groupe__in=groupes_chercheur).delete()
267 #for gc in groupes_chercheur:
268 # adhesion, created = AdhesionGroupe.objects.get_or_create(chercheur=self.chercheur, groupe=gc)
273 class PublicationForm(forms
.ModelForm
):
276 fields
= ('auteurs', 'titre', 'revue', 'annee', 'editeur', 'lieu_edition', 'nb_pages', 'url')
278 PublicationFormSet
= inlineformset_factory(Chercheur
, Publication
, form
=PublicationForm
, extra
=1)
280 class TheseForm(forms
.ModelForm
):
283 fields
= ('titre', 'annee', 'directeur', 'etablissement', 'nb_pages', 'url')
285 class ExpertiseForm(forms
.ModelForm
):
286 organisme_demandeur_visible
= forms
.ChoiceField(
287 label
="Voulez-vous que l'organisme demandeur soit visible sur votre fiche?",
288 choices
=OUI_NON_CHOICES
, widget
=forms
.RadioSelect(), required
=False
290 nom
= forms
.CharField(label
="Objet de l'expertise", required
=False)
294 fields
= ('nom', 'date', 'organisme_demandeur', 'organisme_demandeur_visible')
296 def clean_organisme_demandeur_visible(self
):
297 value
= self
.cleaned_data
['organisme_demandeur_visible']
298 return value
== 'True'
300 ExpertiseFormSet
= inlineformset_factory(Chercheur
, Expertise
, form
=ExpertiseForm
, extra
=1)
302 class ChercheurFormGroup(object):
303 """Groupe de formulaires nécessaires pour l'inscription et l'édition
306 def __init__(self
, data
=None, chercheur
=None):
308 these
= chercheur
and chercheur
.these
309 except These
.DoesNotExist
:
311 chercheur_form_class
= ChercheurInscriptionForm
if chercheur
is None else ChercheurForm
312 self
.chercheur
= chercheur_form_class(data
=data
, prefix
='chercheur', instance
=chercheur
)
313 self
.groupes
= GroupesForm(data
=data
, prefix
='chercheur', chercheur
=chercheur
)
314 self
.expertises
= ExpertiseFormSet(data
=data
, prefix
='expertise', instance
=chercheur
)
315 self
.these
= TheseForm(data
=data
, prefix
='these', instance
=these
)
316 self
.publications
= PublicationFormSet(data
=data
, prefix
='publication', instance
=chercheur
)
319 def has_errors(self
):
320 return bool(self
.chercheur
.errors
or self
.groupes
.errors
or
321 self
.these
.errors
or self
.publications
.errors
or
322 self
.expertises
.errors
)
325 return self
.chercheur
.is_valid() and self
.groupes
.is_valid() and \
326 self
.these
.is_valid() and self
.publications
.is_valid() and \
327 self
.expertises
.is_valid()
332 # Enregistrer d'abord le chercheur lui-même.
333 self
.chercheur
.save()
335 # Puis les objets qui ont des clés étrangères vers nous
336 # puisqu'on a besoin d'un id.
337 chercheur
= self
.chercheur
.instance
338 self
.groupes
.chercheur
= chercheur
340 self
.these
.instance
.chercheur
= chercheur
342 self
.publications
.instance
= chercheur
343 self
.publications
.save()
344 self
.expertises
.instance
= chercheur
345 for expertise
in self
.expertises
.save(commit
=False):
350 return self
.chercheur
.instance
352 class GroupeSearchForm(forms
.ModelForm
):
353 """Formulaire de recherche pour les groupes."""
359 class ChercheurSearchForm(forms
.ModelForm
):
360 """Formulaire de recherche pour les chercheurs."""
363 model
= ChercheurSearch
364 fields
= ['q', 'nom_chercheur', 'domaine',
365 'statut', 'discipline', 'pays', 'region', 'nord_sud',
366 'activites_francophonie', 'genre']
368 class ChercheurSearchEditForm(ChercheurSearchForm
):
369 """Formulaire d'édition d'une recherche sauvegardée."""
371 class Meta(ChercheurSearchForm
.Meta
):
372 fields
= ['nom', 'alerte_courriel'] + ChercheurSearchForm
.Meta
.fields
374 class SendPasswordForm(forms
.Form
):
375 email
= forms
.EmailField(required
=True, label
="Adresse électronique")
376 def clean_email(self
):
377 cleaned_data
= self
.cleaned_data
378 email
= cleaned_data
.get("email")
381 Personne
.objects
.get(courriel
=email
)
383 raise forms
.ValidationError("Cette adresse n'existe pas dans notre base de données.")
386 class SetPasswordForm(forms
.Form
):
387 password
= forms
.CharField(widget
=forms
.PasswordInput(), required
=True, label
="Mot de passe")
388 password_repeat
= forms
.CharField(widget
=forms
.PasswordInput(), required
=True, label
="Confirmez votre mot de passe")
390 def clean_password_repeat(self
):
391 cleaned_data
= self
.cleaned_data
392 password
= cleaned_data
.get("password")
393 password_repeat
= cleaned_data
.get("password_repeat")
394 if password
and password_repeat
:
395 if password
!= password_repeat
:
396 raise forms
.ValidationError("Les mots de passe ne concordent pas")
397 return password_repeat
399 class AuthenticationForm(DjangoAuthenticationForm
):
400 username
= forms
.CharField(label
='Courriel')
403 class MessageForm(forms
.ModelForm
):
407 exclude
= ('chercheur', 'groupe')
410 class ReactiverForm(DjangoSetPasswordForm
):
411 def save(self
, commit
=True):
412 self
.user
= super(ReactiverForm
, self
).save(commit
=False)
413 self
.user
.chercheur
.actif
= True
414 self
.user
.chercheur
.save()
421 class CGStatutForm(forms
.Form
):
422 statut
= forms
.ChoiceField(choices
=CG_STATUT_CHOICES
)