Bug a l'inscription quand il y a des expertises.
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / chercheurs / forms.py
CommitLineData
932eef9a 1# -*- encoding: utf-8 -*-
a7b16ec9 2import hashlib
932eef9a 3from django import forms
3efbacbe 4from django.db.models import Q
ee8b3a49 5from django.forms.models import inlineformset_factory
fbcbdde0 6from itertools import chain
932eef9a 7from models import *
13146d99 8
c073c94d
EMS
9OUI_NON_CHOICES = (('1', 'Oui'), ('0', 'Non'))
10
932eef9a 11class PersonneForm(forms.ModelForm):
c18af6bd 12 genre = forms.ChoiceField(widget=forms.RadioSelect(), choices=GENRE_CHOICES)
e4d01d1d 13
932eef9a 14 class Meta:
dab519fa 15 model = Utilisateur
e4d01d1d
EMS
16 fields = ('nom', 'prenom', 'courriel', 'genre')
17
18class PersonneInscriptionForm(PersonneForm):
19 password = forms.CharField(widget=forms.PasswordInput(), label="Mot de passe")
20
21 class Meta(PersonneForm.Meta):
dab519fa 22 fields = ('nom', 'prenom', 'courriel', 'password', 'genre')
5ecd9e43 23
a7b16ec9
EMS
24 def clean_password(self):
25 """Encrypter le mot de passe avant de le mettre dans la BD."""
26 return hashlib.md5(self.cleaned_data['password']).hexdigest()
932eef9a
AJ
27
28class ChercheurForm(forms.ModelForm):
a7b16ec9 29 """Formulaire d'édition d'un chercheur."""
1de0a686 30 ETABLISSEMENT_CHOICES = ((id, nom if len(nom) < 80 else nom[:80] + '...')
d84e8b50 31 for id, nom in Etablissement.objects.filter(membre=True).values_list('id', 'nom'))
a7b16ec9
EMS
32
33 membre_instance_auf = forms.ChoiceField(
a7b16ec9
EMS
34 label="Êtes-vous (ou avez-vous déjà été) membre d'une instance de l'AUF?",
35 help_text="e.g. conseil scientifique, conseil associatif, commission régionale d'experts",
c073c94d 36 choices=OUI_NON_CHOICES, widget=forms.RadioSelect()
a7b16ec9
EMS
37 )
38 membre_instance_auf_dates = forms.CharField(label="Préciser les dates", required=False)
c073c94d
EMS
39 expert_oif = forms.ChoiceField(label="Êtes-vous expert de l'OIF?", choices=OUI_NON_CHOICES, widget=forms.RadioSelect())
40 membre_association_francophone = forms.ChoiceField(
41 label="Êtes-vous membre d'une association ou d'une société savante francophone?",
42 help_text="e.g. FIPF, Collège international de philosophie, AISLF, etc.",
43 choices=OUI_NON_CHOICES, widget=forms.RadioSelect()
44 )
45 membre_association_francophone_details = forms.CharField(label="Préciser laquelle", required=False)
46 membre_reseau_institutionnel = forms.ChoiceField(
47 label="Avez-vous fait partie des instances d'un réseau institutionnel de l'AUF?",
48 help_text="e.g. AFELSH, RIFFEF, CIDMEF, etc.",
49 choices=OUI_NON_CHOICES, widget=forms.RadioSelect()
50 )
51 membre_reseau_institutionnel_details = forms.CharField(required=False, label="Préciser lesquelles et votre fonction")
52 membre_reseau_institutionnel_dates = forms.CharField(required=False, label="Préciser les dates")
53
fbcbdde0 54 etablissement = forms.ChoiceField(label='Etablissement', required=False, choices=chain([('', '---------')], ETABLISSEMENT_CHOICES))
a7b16ec9 55
932eef9a
AJ
56 class Meta:
57 model = Chercheur
a7b16ec9
EMS
58 fields = ('statut', 'diplome', 'etablissement',
59 'etablissement_autre_nom', 'etablissement_autre_pays',
0b0fbbd7 60 'discipline', 'theme_recherche', 'groupe_recherche', 'mots_cles',
a7b16ec9
EMS
61 'url_site_web', 'url_blog', 'url_reseau_social',
62 'membre_instance_auf', 'membre_instance_auf_dates',
c073c94d
EMS
63 'expert_oif', 'membre_association_francophone', 'membre_association_francophone_details',
64 'membre_reseau_institutionnel', 'membre_reseau_institutionnel_details',
65 'membre_reseau_institutionnel_dates')
7c596de2 66
c073c94d
EMS
67 def clean_membre_instance_auf(self):
68 return bool(int(self.cleaned_data['membre_instance_auf']))
69
70 def clean_membre_instance_auf_dates(self):
71 membre = self.cleaned_data.get('membre_instance_auf')
72 dates = self.cleaned_data.get('membre_instance_auf_dates')
73 if membre and not dates:
74 raise forms.ValidationError('Veuillez préciser les dates')
75 return dates
76
77 def clean_expert_oif(self):
78 return bool(int(self.cleaned_data['expert_oif']))
79
80 def clean_membre_association_francophone(self):
81 return bool(int(self.cleaned_data['membre_association_francophone']))
82
83 def clean_membre_association_francophone_details(self):
84 membre = self.cleaned_data.get('membre_association_francophone')
85 details = self.cleaned_data.get('membre_association_francophone_details')
86 if membre and not details:
87 raise forms.ValidationError('Veuillez préciser')
88 return details
89
90 def clean_membre_reseau_institutionnel(self):
91 return bool(int(self.cleaned_data['membre_reseau_institutionnel']))
92
93 def clean_membre_reseau_institutionnel_details(self):
94 membre = self.cleaned_data.get('membre_reseau_institutionnel')
95 details = self.cleaned_data.get('membre_reseau_institutionnel_details')
96 if membre and not details:
97 raise forms.ValidationError('Veuillez préciser')
98 return details
99
100 def clean_membre_reseau_institutionnel_dates(self):
101 membre = self.cleaned_data.get('membre_reseau_institutionnel')
102 dates = self.cleaned_data.get('membre_reseau_institutionnel_dates')
103 if membre and not dates:
104 raise forms.ValidationError('Veuillez préciser les dates')
105 return dates
106
1de0a686 107 def clean_etablissement(self):
fbcbdde0
EMS
108 etablissement = self.cleaned_data['etablissement']
109 if etablissement:
110 return Etablissement.objects.get(id=etablissement)
1de0a686 111
a7b16ec9
EMS
112 def clean(self):
113 etablissement = self.cleaned_data['etablissement']
114 etablissement_autre_nom = self.cleaned_data['etablissement_autre_nom']
115 etablissement_autre_pays = self.cleaned_data['etablissement_autre_pays']
116 if not etablissement:
117 if not etablissement_autre_nom:
118 self._errors['etablissement'] = self.error_class([u"Vous devez renseigner l'établissement"])
119 elif not etablissement_autre_pays:
120 self._errors['etablissement_autre_pays'] = self.error_class([u"Vous devez renseigner le pays de l'établissement"])
121 return self.cleaned_data
122
a7b16ec9
EMS
123class GroupesForm(forms.Form):
124 """Formulaire qui associe des groupes à un chercheur."""
e4d01d1d
EMS
125 groupes = forms.ModelMultipleChoiceField(
126 queryset=Groupe.objects.all(),
127 label='Domaines de recherche', required=False,
128 help_text="Maintenez appuyé « Ctrl », ou « Commande (touche pomme) » sur un Mac, pour en sélectionner plusieurs."
129 )
a7b16ec9
EMS
130
131 def __init__(self, data=None, prefix=None, chercheur=None):
132 self.chercheur = chercheur
133 initial = {}
134 if chercheur:
135 initial['groupes'] = chercheur.groupes.values_list('id', flat=True)
136 super(GroupesForm, self).__init__(data=data, prefix=prefix, initial=initial)
137
138 def save(self):
139 if self.is_valid():
140 groupes = self.cleaned_data['groupes']
141 ChercheurGroupe.objects.filter(chercheur=self.chercheur).exclude(groupe__in=groupes).delete()
142 for g in groupes:
143 ChercheurGroupe.objects.get_or_create(chercheur=self.chercheur, groupe=g, actif=1)
144
00755d9b
AJ
145class PublicationForm(forms.ModelForm):
146 class Meta:
147 model = Publication
5fb54817 148 fields = ('titre', 'revue', 'annee', 'editeur', 'lieu_edition', 'nb_pages', 'url')
f810842d
AJ
149
150class TheseForm(PublicationForm):
2a36714f 151 titre = forms.CharField(required=True, label="Titre de la thèse ou du mémoire")
a4e383ac 152 annee = forms.IntegerField(required=True, label="Année de soutenance (réalisée ou prévue)")
dbade9d7 153 editeur = forms.CharField(required=True, label="Directeur de thèse ou de mémoire")
29f922e0 154 lieu_edition = forms.CharField(required=True, label="Établissement de soutenance")
e8e9e4fd
AJ
155 class Meta:
156 model = Publication
2a36714f
AJ
157 fields = ('titre', 'annee', 'editeur', 'lieu_edition', 'nb_pages', 'url')
158
5b9abc81 159class ExpertiseForm(forms.ModelForm):
c073c94d
EMS
160 organisme_demandeur_visible = forms.ChoiceField(
161 label="Voulez-vous que l'organisme demandeur soit visible sur votre fiche?",
162 choices=OUI_NON_CHOICES, widget=forms.RadioSelect(), required=False
163 )
5b9abc81
AJ
164 class Meta:
165 model = Expertise
166 fields = ('nom', 'date', 'organisme_demandeur', 'organisme_demandeur_visible')
dab519fa 167
b16bcbaf 168 def clean_organisme_demandeur_visible(self):
6504a7e5
EMS
169 value = self.cleaned_data['organisme_demandeur_visible']
170 return bool(int(value)) if value else False
b16bcbaf 171
ee8b3a49
EMS
172ExpertiseFormSet = inlineformset_factory(Chercheur, Expertise, form=ExpertiseForm, extra=1)
173
a7b16ec9
EMS
174class ChercheurFormGroup(object):
175 """Groupe de formulaires nécessaires pour l'inscription et l'édition
176 d'un chercheur."""
00755d9b 177
a7b16ec9 178 def __init__(self, data=None, chercheur=None):
e4d01d1d 179 personne_form_class = PersonneInscriptionForm if chercheur is None else PersonneForm
a7b16ec9
EMS
180 self.chercheur = ChercheurForm(data=data, prefix='chercheur', instance=chercheur)
181 self.groupes = GroupesForm(data=data, prefix='chercheur', chercheur=chercheur)
182 self.personne = personne_form_class(data=data, prefix='personne', instance=chercheur and chercheur.personne)
183 self.publication1 = PublicationForm(data=data, prefix='publication1', instance=chercheur and chercheur.publication1)
184 self.publication2 = PublicationForm(data=data, prefix='publication2', instance=chercheur and chercheur.publication2)
185 self.publication3 = PublicationForm(data=data, prefix='publication3', instance=chercheur and chercheur.publication3)
186 self.publication4 = PublicationForm(data=data, prefix='publication4', instance=chercheur and chercheur.publication4)
187 self.these = TheseForm(data=data, prefix='these', instance=chercheur and chercheur.these)
ee8b3a49 188 self.expertises = ExpertiseFormSet(data=data, prefix='expertise', instance=chercheur)
a7b16ec9
EMS
189
190 @property
191 def has_errors(self):
192 return bool(self.chercheur.errors or self.personne.errors or self.groupes.errors or
193 self.publication1.errors or self.publication2.errors or self.publication3.errors or
ee8b3a49 194 self.publication4.errors or self.these.errors or self.expertises.errors)
a7b16ec9
EMS
195
196 def is_valid(self):
197 return self.chercheur.is_valid() and self.personne.is_valid() and self.groupes.is_valid() and \
198 self.publication1.is_valid() and self.publication2.is_valid() and \
199 self.publication3.is_valid() and self.publication4.is_valid() and \
ee8b3a49 200 self.these.is_valid() and self.expertises.is_valid()
a7b16ec9
EMS
201
202 def save(self):
203 if self.is_valid():
204
205 chercheur = self.chercheur.instance
206
207 # Enregistrer d'abord les clés étrangères car on doit les stocker dans
208 # l'objet chercheur.
209 chercheur.personne = self.personne.save()
210 if self.publication1.cleaned_data['titre']:
211 chercheur.publication1 = self.publication1.save()
212 if self.publication2.cleaned_data['titre']:
213 chercheur.publication2 = self.publication2.save()
214 if self.publication3.cleaned_data['titre']:
215 chercheur.publication3 = self.publication3.save()
216 if self.publication4.cleaned_data['titre']:
217 chercheur.publication4 = self.publication4.save()
218 chercheur.these = self.these.save()
a7b16ec9
EMS
219
220 # Puis enregistrer le chercheur lui-même.
221 self.chercheur.save()
222
223 # Puis les many-to-many puisqu'on a besoin d'un id.
224 self.groupes.chercheur = chercheur
225 self.groupes.save()
3820b46e
EMS
226 self.expertises.instance = chercheur
227 self.expertises.save()
5b9abc81 228
13146d99 229class RepertoireSearchForm (forms.Form):
f0692c02 230 q = forms.CharField(required=False, label="Rechercher dans tous les champs")
3efbacbe 231 nom = forms.CharField(required=False, label="Nom")
0e9597af 232 domaine = forms.ModelChoiceField(queryset=Groupe.objects.all(), required=False, label="Domaine de recherche", empty_label="Tous")
bc415771
EMS
233 groupe_recherche = forms.CharField(required=False, label="Groupe de recherche",
234 help_text="ou Laboratoire, ou Groupement inter-universitaire")
6bd49ff1 235 statut = forms.ChoiceField(choices=(('','Tous'),)+STATUT_CHOICES+(('expert','Expert'),), required=False, label="Statut")
f0692c02 236 discipline = forms.ModelChoiceField(queryset=Discipline.objects.all(), required=False, label="Discipline", empty_label="Toutes")
3eba0476 237 pays = forms.ModelChoiceField(queryset=Pays.objects.all(), required=False, label="Pays", empty_label="Tous")
bc415771
EMS
238 region = forms.ModelChoiceField(queryset=Region.objects.all(), required=False, label="Région", empty_label="Toutes",
239 help_text="La région est ici définie au sens, non strictement géographique, du Bureau régional de l'AUF de référence.")
bc415771
EMS
240 nord_sud = forms.ChoiceField(choices=(('', 'Tous'), ('Nord', 'Nord'), ('Sud', 'Sud')), required=False, label="Nord/Sud",
241 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 les plus développés, par Sud les pays en voie de développement.")
c548d94a
EMS
242
243 def __init__(self, data=None, region=None):
244 super(RepertoireSearchForm, self).__init__(data)
245 if region:
246 pays = self.fields['pays']
247 pays.queryset = pays.queryset.filter(region=region)
248
3efbacbe
EMS
249 def get_query_set(self):
250 qs = Chercheur.objects.all()
251 if self.is_valid():
252 nom = self.cleaned_data['nom']
253 if nom:
254 qs = qs.search_nom(nom)
3efbacbe
EMS
255 domaine = self.cleaned_data["domaine"]
256 if domaine:
257 qs = qs.filter(groupes=domaine)
d087521a
EMS
258 groupe_recherche = self.cleaned_data['groupe_recherche']
259 if groupe_recherche:
260 for word in groupe_recherche.split():
261 qs = qs.filter(groupe_recherche__icontains=word)
f0692c02
EMS
262 q = self.cleaned_data["q"]
263 if q:
264 qs = qs.search(q)
3efbacbe
EMS
265 statut = self.cleaned_data["statut"]
266 if statut:
267 if statut == "expert":
ee8b3a49 268 qs = qs.exclude(expertises=None)
3efbacbe
EMS
269 else:
270 qs = qs.filter(statut=statut)
f0692c02
EMS
271 discipline = self.cleaned_data['discipline']
272 if discipline:
273 qs = qs.filter_discipline(discipline)
274 region = self.cleaned_data['region']
275 if region:
276 qs = qs.filter_region(region)
62eece34
EMS
277 pays = self.cleaned_data["pays"]
278 if pays:
279 qs = qs.filter(Q(etablissement__pays=pays) | Q(etablissement_autre_pays=pays))
62eece34
EMS
280 nord_sud = self.cleaned_data['nord_sud']
281 if nord_sud:
282 qs = qs.filter(Q(etablissement__pays__nord_sud=nord_sud) | Q(etablissement_autre_pays__nord_sud=nord_sud))
3efbacbe
EMS
283 return qs
284
0e9597af 285class SendPasswordForm(forms.Form):
89da853e 286 email = forms.EmailField(required=True, label="Adresse électronique")
0e9597af
AJ
287 def clean_email(self):
288 cleaned_data = self.cleaned_data
289 email = cleaned_data.get("email")
290 if email:
291 try:
292 Utilisateur.objects.get(courriel=email)
293 except:
89da853e 294 raise forms.ValidationError("Cette adresse n'existe pas dans notre base de données.")
e427f068
AJ
295 return email
296
297class NewPasswordForm(forms.Form):
298 password = forms.CharField(widget=forms.PasswordInput(), required=True, label="Mot de passe")
299 password_repeat = forms.CharField(widget=forms.PasswordInput(), required=True, label="Confirmez mot de passe")
300 def clean_password_repeat(self):
301 cleaned_data = self.cleaned_data
302 password = cleaned_data.get("password")
303 password_repeat = cleaned_data.get("password_repeat")
304 if password and password_repeat:
305 if password != password_repeat:
306 raise forms.ValidationError("Les mots de passe ne concordent pas")
307 return password_repeat
0e9597af 308