1 # -*- encoding: utf-8 -*-
3 from django
import forms
4 from django
.db
.models
import Q
5 from django
.forms
.models
import inlineformset_factory
6 from itertools
import chain
9 OUI_NON_CHOICES
= (('1', 'Oui'), ('0', 'Non'))
11 class PersonneForm(forms
.ModelForm
):
12 genre
= forms
.ChoiceField(widget
=forms
.RadioSelect(), choices
=GENRE_CHOICES
)
16 fields
= ('nom', 'prenom', 'courriel', 'genre')
18 class PersonneInscriptionForm(PersonneForm
):
19 password
= forms
.CharField(widget
=forms
.PasswordInput(), label
="Mot de passe")
21 class Meta(PersonneForm
.Meta
):
22 fields
= ('nom', 'prenom', 'courriel', 'password', 'genre')
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()
28 class ChercheurForm(forms
.ModelForm
):
29 """Formulaire d'édition d'un chercheur."""
30 ETABLISSEMENT_CHOICES
= ((id, nom
if len(nom
) < 80 else nom
[:80] + '...')
31 for id, nom
in Etablissement
.objects
.filter(membre
=True).values_list('id', 'nom'))
33 membre_instance_auf
= forms
.ChoiceField(
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",
36 choices
=OUI_NON_CHOICES
, widget
=forms
.RadioSelect()
38 membre_instance_auf_dates
= forms
.CharField(label
="Préciser les dates", required
=False)
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()
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()
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")
54 etablissement
= forms
.ChoiceField(label
='Etablissement', required
=False, choices
=chain([('', '---------')], ETABLISSEMENT_CHOICES
))
58 fields
= ('statut', 'diplome', 'etablissement',
59 'etablissement_autre_nom', 'etablissement_autre_pays',
60 'discipline', 'theme_recherche', 'groupe_recherche', 'mots_cles',
61 'url_site_web', 'url_blog', 'url_reseau_social',
62 'membre_instance_auf', 'membre_instance_auf_dates',
63 'expert_oif', 'membre_association_francophone', 'membre_association_francophone_details',
64 'membre_reseau_institutionnel', 'membre_reseau_institutionnel_details',
65 'membre_reseau_institutionnel_dates')
67 def clean_membre_instance_auf(self
):
68 return bool(int(self
.cleaned_data
['membre_instance_auf']))
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')
77 def clean_expert_oif(self
):
78 return bool(int(self
.cleaned_data
['expert_oif']))
80 def clean_membre_association_francophone(self
):
81 return bool(int(self
.cleaned_data
['membre_association_francophone']))
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')
90 def clean_membre_reseau_institutionnel(self
):
91 return bool(int(self
.cleaned_data
['membre_reseau_institutionnel']))
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')
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')
107 def clean_etablissement(self
):
108 etablissement
= self
.cleaned_data
['etablissement']
110 return Etablissement
.objects
.get(id=etablissement
)
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
123 class GroupesForm(forms
.Form
):
124 """Formulaire qui associe des groupes à un chercheur."""
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."
131 def __init__(self
, data
=None, prefix
=None, chercheur
=None):
132 self
.chercheur
= chercheur
135 initial
['groupes'] = chercheur
.groupes
.values_list('id', flat
=True)
136 super(GroupesForm
, self
).__init__(data
=data
, prefix
=prefix
, initial
=initial
)
140 groupes
= self
.cleaned_data
['groupes']
141 ChercheurGroupe
.objects
.filter(chercheur
=self
.chercheur
).exclude(groupe__in
=groupes
).delete()
143 ChercheurGroupe
.objects
.get_or_create(chercheur
=self
.chercheur
, groupe
=g
, actif
=1)
145 class PublicationForm(forms
.ModelForm
):
148 fields
= ('titre', 'revue', 'annee', 'editeur', 'lieu_edition', 'nb_pages', 'url')
150 class TheseForm(PublicationForm
):
151 titre
= forms
.CharField(required
=True, label
="Titre de la thèse ou du mémoire")
152 annee
= forms
.IntegerField(required
=True, label
="Année de soutenance (réalisée ou prévue)")
153 editeur
= forms
.CharField(required
=True, label
="Directeur de thèse ou de mémoire")
154 lieu_edition
= forms
.CharField(required
=True, label
="Établissement de soutenance")
157 fields
= ('titre', 'annee', 'editeur', 'lieu_edition', 'nb_pages', 'url')
159 class ExpertiseForm(forms
.ModelForm
):
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
166 fields
= ('nom', 'date', 'organisme_demandeur', 'organisme_demandeur_visible')
168 def clean_organisme_demandeur_visible(self
):
169 value
= self
.cleaned_data
['organisme_demandeur_visible']
170 return bool(int(value
)) if value
else False
172 ExpertiseFormSet
= inlineformset_factory(Chercheur
, Expertise
, form
=ExpertiseForm
, extra
=1)
174 class ChercheurFormGroup(object):
175 """Groupe de formulaires nécessaires pour l'inscription et l'édition
178 def __init__(self
, data
=None, chercheur
=None):
179 personne_form_class
= PersonneInscriptionForm
if chercheur
is None else PersonneForm
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
)
188 self
.expertises
= ExpertiseFormSet(data
=data
, prefix
='expertise', instance
=chercheur
)
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
194 self
.publication4
.errors
or self
.these
.errors
or self
.expertises
.errors
)
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 \
200 self
.these
.is_valid() and self
.expertises
.is_valid()
205 chercheur
= self
.chercheur
.instance
207 # Enregistrer d'abord les clés étrangères car on doit les stocker dans
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()
219 self
.expertises
.save()
221 # Puis enregistrer le chercheur lui-même.
222 self
.chercheur
.save()
224 # Puis les many-to-many puisqu'on a besoin d'un id.
225 self
.groupes
.chercheur
= chercheur
228 class RepertoireSearchForm (forms
.Form
):
229 q
= forms
.CharField(required
=False, label
="Rechercher dans tous les champs")
230 nom
= forms
.CharField(required
=False, label
="Nom")
231 domaine
= forms
.ModelChoiceField(queryset
=Groupe
.objects
.all(), required
=False, label
="Domaine de recherche", empty_label
="Tous")
232 groupe_recherche
= forms
.CharField(required
=False, label
="Groupe de recherche")
233 statut
= forms
.ChoiceField(choices
=(('','Tous'),)+STATUT_CHOICES
+(('expert','Expert'),), required
=False, label
="Statut")
234 discipline
= forms
.ModelChoiceField(queryset
=Discipline
.objects
.all(), required
=False, label
="Discipline", empty_label
="Toutes")
235 region
= forms
.ModelChoiceField(queryset
=Region
.objects
.all(), required
=False, label
="Région", empty_label
="Toutes")
236 pays
= forms
.ModelChoiceField(queryset
=Pays
.objects
.all(), required
=False, label
="Pays", empty_label
="Tous")
237 nord_sud
= forms
.ChoiceField(choices
=(('', 'Tous'), ('Nord', 'Nord'), ('Sud', 'Sud')), required
=False, label
="Nord/Sud")
239 def __init__(self
, data
=None, region
=None):
240 super(RepertoireSearchForm
, self
).__init__(data
)
242 pays
= self
.fields
['pays']
243 pays
.queryset
= pays
.queryset
.filter(region
=region
)
245 def get_query_set(self
):
246 qs
= Chercheur
.objects
.all()
248 nom
= self
.cleaned_data
['nom']
250 qs
= qs
.search_nom(nom
)
251 domaine
= self
.cleaned_data
["domaine"]
253 qs
= qs
.filter(groupes
=domaine
)
254 groupe_recherche
= self
.cleaned_data
['groupe_recherche']
256 for word
in groupe_recherche
.split():
257 qs
= qs
.filter(groupe_recherche__icontains
=word
)
258 q
= self
.cleaned_data
["q"]
261 statut
= self
.cleaned_data
["statut"]
263 if statut
== "expert":
264 qs
= qs
.exclude(expertises
=None)
266 qs
= qs
.filter(statut
=statut
)
267 discipline
= self
.cleaned_data
['discipline']
269 qs
= qs
.filter_discipline(discipline
)
270 region
= self
.cleaned_data
['region']
272 qs
= qs
.filter_region(region
)
273 pays
= self
.cleaned_data
["pays"]
275 qs
= qs
.filter(Q(etablissement__pays
=pays
) |
Q(etablissement_autre_pays
=pays
))
276 nord_sud
= self
.cleaned_data
['nord_sud']
278 qs
= qs
.filter(Q(etablissement__pays__nord_sud
=nord_sud
) |
Q(etablissement_autre_pays__nord_sud
=nord_sud
))
281 class SendPasswordForm(forms
.Form
):
282 email
= forms
.EmailField(required
=True, label
="Adresse électronique")
283 def clean_email(self
):
284 cleaned_data
= self
.cleaned_data
285 email
= cleaned_data
.get("email")
288 Utilisateur
.objects
.get(courriel
=email
)
290 raise forms
.ValidationError("Cette adresse n'existe pas dans notre base de données.")
293 class NewPasswordForm(forms
.Form
):
294 password
= forms
.CharField(widget
=forms
.PasswordInput(), required
=True, label
="Mot de passe")
295 password_repeat
= forms
.CharField(widget
=forms
.PasswordInput(), required
=True, label
="Confirmez mot de passe")
296 def clean_password_repeat(self
):
297 cleaned_data
= self
.cleaned_data
298 password
= cleaned_data
.get("password")
299 password_repeat
= cleaned_data
.get("password_repeat")
300 if password
and password_repeat
:
301 if password
!= password_repeat
:
302 raise forms
.ValidationError("Les mots de passe ne concordent pas")
303 return password_repeat