Commit | Line | Data |
---|---|---|
6f8d521e | 1 | # -*- coding: utf-8 -*- |
44a788a6 | 2 | from auf.django.references import models as ref |
6f8d521e | 3 | from django.db.models import Q |
cbae0173 | 4 | from django.contrib import admin |
55ef8558 | 5 | from django.core.urlresolvers import reverse as url |
55ef8558 | 6 | from django.http import HttpResponseRedirect |
7b0b2f96 | 7 | from django.contrib.auth.models import User |
cbae0173 | 8 | |
81fe476e PP |
9 | from chercheurs.models import Chercheur, ChercheurVoir, Publication, \ |
10 | GroupeChercheur, DomaineRecherche, \ | |
dca3ff65 PP |
11 | AdhesionGroupe, ChercheurQuerySet, \ |
12 | AdhesionCommunaute, AdhesionDomaineRecherche, \ | |
549417d6 | 13 | Groupe, Message |
66386d77 | 14 | from chercheurs.utils import export |
2094c7e5 | 15 | from savoirs.models import Search |
6f8d521e | 16 | |
b7816629 | 17 | |
44a788a6 EMS |
18 | class PaysListFilter(admin.SimpleListFilter): |
19 | title = 'pays' | |
20 | parameter_name = 'pays' | |
21 | ||
22 | def lookups(self, request, model_admin): | |
23 | region = request.GET.get('region') | |
24 | nord_sud = request.GET.get('nord_sud') | |
25 | pays = ref.Pays.objects.all() | |
26 | if region is not None: | |
27 | pays = pays.filter(region=region) | |
28 | if nord_sud is not None: | |
29 | pays = pays.filter(nord_sud=nord_sud) | |
30 | return pays.values_list('code', 'nom') | |
31 | ||
32 | def queryset(self, request, queryset): | |
33 | if self.value() is not None: | |
34 | return queryset.filter( | |
35 | Q(etablissement__pays=self.value()) | | |
36 | Q(etablissement=None, | |
37 | etablissement_autre_pays=self.value()) | |
38 | ) | |
39 | ||
40 | ||
41 | class ParamRemovingListFilter(admin.SimpleListFilter): | |
42 | remove_params = [] | |
43 | ||
44 | def choices(self, cl): | |
45 | yield { | |
46 | 'selected': self.value() is None, | |
47 | 'query_string': cl.get_query_string( | |
48 | {}, [self.parameter_name] + self.remove_params | |
49 | ), | |
50 | 'display': 'Tout', | |
51 | } | |
52 | for lookup, title in self.lookup_choices: | |
53 | yield { | |
54 | 'selected': self.value() == lookup, | |
55 | 'query_string': cl.get_query_string({ | |
56 | self.parameter_name: lookup, | |
57 | }, self.remove_params), | |
58 | 'display': title, | |
59 | } | |
60 | ||
61 | ||
62 | class RegionListFilter(ParamRemovingListFilter): | |
63 | title = 'région' | |
64 | parameter_name = 'region' | |
65 | remove_params = ['pays'] | |
66 | ||
67 | def lookups(self, request, model_admin): | |
68 | return ( | |
69 | (str(id), nom) | |
70 | for id, nom in ref.Region.objects.values_list('id', 'nom') | |
71 | ) | |
72 | ||
73 | def queryset(self, request, queryset): | |
74 | if self.value() is not None: | |
75 | return queryset.filter( | |
76 | Q(etablissement__pays__region=self.value()) | | |
77 | Q(etablissement=None, | |
78 | etablissement_autre_pays__region=self.value()) | |
79 | ) | |
80 | ||
81 | ||
82 | class NordSudListFilter(ParamRemovingListFilter): | |
83 | title = 'nord/sud' | |
84 | parameter_name = 'nord_sud' | |
85 | remove_params = ['pays'] | |
86 | ||
87 | def lookups(self, request, model_admin): | |
88 | return ref.Pays.NORD_SUD_CHOICES | |
89 | ||
90 | def queryset(self, request, queryset): | |
91 | if self.value() is not None: | |
92 | return queryset.filter( | |
93 | Q(etablissement__pays__nord_sud=self.value()) | | |
94 | Q(etablissement=None, | |
95 | etablissement_autre_pays__nord_sud=self.value()) | |
96 | ) | |
97 | ||
98 | ||
99 | class ExpertListFilter(admin.SimpleListFilter): | |
100 | title = 'expert' | |
101 | parameter_name = 'expert' | |
102 | ||
103 | def lookups(self, request, model_admin): | |
104 | return ( | |
105 | ('1', 'Oui'), | |
106 | ('0', 'Non'), | |
107 | ) | |
108 | ||
109 | def queryset(self, request, queryset): | |
110 | if self.value() in ['1', 1, True]: | |
111 | return queryset.exclude(expertises=None) | |
112 | elif self.value() in ['0', 0, False]: | |
113 | return queryset.filter(expertises=None) | |
114 | ||
115 | ||
116 | class GroupeChercheursListFilter(admin.SimpleListFilter): | |
117 | title = 'groupe de chercheurs' | |
118 | parameter_name = 'groupe_chercheurs' | |
119 | ||
120 | def lookups(self, request, model_admin): | |
121 | return ( | |
122 | (str(id), nom) | |
123 | for id, nom in GroupeChercheur.objects.values_list('id', 'nom') | |
124 | ) | |
125 | ||
126 | def queryset(self, request, queryset): | |
90cb60a0 EMS |
127 | if self.value(): |
128 | return queryset.filter(groupes=self.value()) | |
44a788a6 EMS |
129 | |
130 | ||
131 | class DomaineRechercheListFilter(admin.SimpleListFilter): | |
132 | title = 'domaine de recherche' | |
133 | parameter_name = 'domaine_recherche' | |
134 | ||
135 | def lookups(self, request, model_admin): | |
136 | return ( | |
137 | (str(id), nom) | |
138 | for id, nom in DomaineRecherche.objects.values_list('id', 'nom') | |
139 | ) | |
140 | ||
141 | def queryset(self, request, queryset): | |
90cb60a0 EMS |
142 | if self.value(): |
143 | return queryset.filter(groupes=self.value()) | |
44a788a6 EMS |
144 | |
145 | ||
55ef8558 | 146 | class ChercheurAdmin(admin.ModelAdmin): |
44a788a6 EMS |
147 | list_filter = ( |
148 | 'genre', 'statut', 'membre_reseau_institutionnel', | |
149 | 'membre_instance_auf', 'discipline', RegionListFilter, | |
150 | NordSudListFilter, PaysListFilter, GroupeChercheursListFilter, | |
151 | DomaineRechercheListFilter, ExpertListFilter | |
152 | ) | |
b1d4c7ac PP |
153 | alphabet_filter = 'nom' |
154 | alphabet_filter_table = 'chercheurs_personne' | |
155 | DEFAULT_ALPHABET = '' | |
156 | ||
d264c787 | 157 | actions = ('remove_from_group', 'export_as_ods', 'export_as_csv') |
62354bdb | 158 | search_fields = ('nom', 'prenom') |
cbae0173 | 159 | |
8afac00d PP |
160 | exclude = ('user',) |
161 | ||
afc30c28 | 162 | def lookup_allowed(self, lookup, value): |
b7816629 EMS |
163 | return lookup in ['genre', 'statut', 'membre_reseau_institutionnel', |
164 | 'membre_instance_auf', 'discipline', 'region', | |
165 | 'pays', 'groupes', 'nord_sud'] or \ | |
afc30c28 | 166 | admin.ModelAdmin.lookup_allowed(self, lookup, value) |
c0d2903e | 167 | |
55ef8558 EMS |
168 | def remove_from_group(self, request, queryset): |
169 | groupe_id = request.GET.get('groupes__id__exact') | |
170 | chercheur_ids = queryset.values_list('id', flat=True) | |
b7816629 EMS |
171 | matches = AdhesionGroupe.objects.filter( |
172 | groupe=groupe_id, chercheur__in=chercheur_ids | |
173 | ) | |
55ef8558 | 174 | matches.delete() |
b7816629 EMS |
175 | return HttpResponseRedirect( |
176 | url('admin:chercheurs_chercheur_changelist') + | |
177 | '?groupes__id__exact=' + groupe_id | |
178 | ) | |
55ef8558 EMS |
179 | |
180 | def get_actions(self, request): | |
181 | actions = super(ChercheurAdmin, self).get_actions(request) | |
182 | ||
35b0778c | 183 | # Si on filtre par groupes, offrir d'en retirer les |
55ef8558 EMS |
184 | # chercheurs sélectionnés. |
185 | groupe_id = request.GET.get('groupes__id__exact') | |
186 | if groupe_id: | |
187 | groupe = Groupe.objects.get(id=groupe_id) | |
188 | action_desc = actions['remove_from_group'] | |
b7816629 EMS |
189 | actions['remove_from_group'] = ( |
190 | action_desc[0], | |
191 | action_desc[1], | |
192 | u'Retirer du domaine de recherche « %s »' % groupe.nom | |
193 | ) | |
55ef8558 EMS |
194 | else: |
195 | del actions['remove_from_group'] | |
196 | return actions | |
197 | ||
6f8d521e | 198 | def queryset(self, request): |
120891b9 | 199 | return ChercheurAdminQuerySet(Chercheur).filter(actif=True) |
6f8d521e | 200 | |
ee2ef0e8 | 201 | def get_object(self, request, object_id): |
b7816629 EMS |
202 | """ |
203 | On doit réimplémenter cette méthode à cause de ce qu'on fait avec | |
204 | ``initial`` dans la méthode queryset(). | |
205 | """ | |
ee2ef0e8 EMS |
206 | try: |
207 | return Chercheur.objects.get(id=object_id) | |
208 | except Chercheur.DoesNotExist: | |
209 | return None | |
210 | ||
a5891f39 PP |
211 | def has_add_permission(self, request, obj=None): |
212 | return False | |
d264c787 EMS |
213 | |
214 | def export_as_csv(self, request, queryset): | |
66386d77 | 215 | return export(queryset, 'csv') |
d264c787 EMS |
216 | export_as_csv.short_description = 'Export CSV' |
217 | ||
218 | def export_as_ods(self, request, queryset): | |
66386d77 | 219 | return export(queryset, 'ods') |
d264c787 EMS |
220 | export_as_ods.short_description = 'Export ODS' |
221 | ||
81fe476e PP |
222 | |
223 | class ChercheurVoirAdmin(ChercheurAdmin): | |
224 | ||
225 | list_editable = [] | |
b7816629 EMS |
226 | fields = ['salutation', 'nom', 'prenom', 'courriel', |
227 | 'afficher_courriel', 'fonction', 'date_naissance', | |
228 | 'sousfonction', 'telephone', 'adresse_postale', 'genre', | |
229 | 'commentaire', 'nationalite', 'statut', 'diplome', | |
230 | 'etablissement', 'etablissement_autre_nom', | |
231 | 'etablissement_autre_pays', 'attestation', 'thematique', | |
232 | 'mots_cles', 'discipline', 'theme_recherche', | |
233 | 'equipe_recherche', 'url_site_web', 'url_blog', | |
234 | 'url_reseau_social', 'membre_instance_auf', | |
235 | 'membre_instance_auf_nom', 'membre_instance_auf_fonction', | |
236 | 'membre_instance_auf_dates', 'expert_oif', | |
237 | 'expert_oif_details', 'expert_oif_dates', | |
238 | 'membre_association_francophone', | |
239 | 'membre_association_francophone_details', | |
240 | 'membre_reseau_institutionnel', | |
241 | 'membre_reseau_institutionnel_nom', | |
242 | 'membre_reseau_institutionnel_fonction', | |
243 | 'membre_reseau_institutionnel_dates', 'expertises_auf'] | |
81fe476e PP |
244 | |
245 | def __init__(self, model, admin_site): | |
246 | super(ChercheurVoirAdmin, self).__init__(model, admin_site) | |
247 | self.readonly_fields = self.fields | |
248 | ||
81fe476e PP |
249 | admin.site.register(ChercheurVoir, ChercheurVoirAdmin) |
250 | ||
b7816629 | 251 | |
6f8d521e EMS |
252 | class ChercheurAdminQuerySet(ChercheurQuerySet): |
253 | ||
120891b9 PP |
254 | def delete(self): |
255 | self.update(actif=False) | |
256 | ||
cec3f8db | 257 | |
18407f73 | 258 | class AdhesionGroupeAdmin(admin.ModelAdmin): |
b7816629 | 259 | list_filter = ('groupe', 'statut') |
61c05759 PP |
260 | list_display = ('groupe', 'chercheur', 'statut') |
261 | list_editable = ('statut',) | |
5cba4157 | 262 | search_fields = ('chercheur__nom', 'chercheur__prenom') |
4ef9751d | 263 | |
b0db5c3e PP |
264 | alphabet_filter = 'chercheur__nom' |
265 | DEFAULT_ALPHABET = '' | |
266 | ||
1fd4a630 PP |
267 | actions = ['assigner_cgstatut'] |
268 | ||
b0db5c3e PP |
269 | def lookup_allowed(self, lookup, value): |
270 | return lookup in ['chercheur__nom__istartswith'] or \ | |
271 | admin.ModelAdmin.lookup_allowed(self, lookup, value) | |
272 | ||
4ef9751d | 273 | def queryset(self, request): |
18407f73 | 274 | qs = super(AdhesionGroupeAdmin, self).queryset(request) |
4ef9751d | 275 | |
b7816629 EMS |
276 | if not request.user.is_superuser \ |
277 | and not request.user.has_perm('chercheurs.change_adhesiongroupe'): | |
4ef9751d PP |
278 | qs = qs.filter(groupe__responsables=request.user) |
279 | ||
280 | return qs | |
281 | ||
282 | def has_change_permission(self, request, obj=None): | |
283 | ||
284 | if not obj: | |
285 | if request.user.responsable_groupe.count(): | |
286 | return True | |
287 | else: | |
288 | if request.user in obj.groupe.responsables.all(): | |
289 | return True | |
290 | ||
b7816629 EMS |
291 | return super(AdhesionGroupeAdmin, self) \ |
292 | .has_change_permission(request, obj) | |
4ef9751d | 293 | |
1fd4a630 PP |
294 | def assigner_cgstatut(self, request, queryset): |
295 | selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME) | |
b7816629 EMS |
296 | return HttpResponseRedirect( |
297 | "/admin/assigner_%s?ids=%s" % ('cgstatut', ",".join(selected)) | |
298 | ) | |
1fd4a630 PP |
299 | assigner_cgstatut.short_description = u'Assigner un statut' |
300 | ||
6d5279ff | 301 | |
dca3ff65 PP |
302 | class AdhesionCommunauteAdmin(AdhesionGroupeAdmin): |
303 | pass | |
304 | ||
305 | ||
306 | class AdhesionDomaineRechercheAdmin(AdhesionGroupeAdmin): | |
307 | pass | |
308 | ||
b7816629 | 309 | |
44e07248 | 310 | class BaseGroupeAdmin(admin.ModelAdmin): |
b803eb99 | 311 | search_fields = ['nom'] |
6d5279ff | 312 | fieldsets = ( |
0c0d997c PP |
313 | (('Options générales'), {'fields': ('nom', 'url', 'liste_diffusion', |
314 | 'bulletin', 'page_accueil')}), | |
34d0147e | 315 | (('Gestionnaire de communauté'), {'fields': ('responsables',)}), |
2094c7e5 | 316 | (('Recherches prédéfinies'), {'fields': ('recherches',)}), |
6d5279ff | 317 | ) |
cec3f8db | 318 | |
0c0d997c PP |
319 | class Media: |
320 | js = ['js/tiny_mce/tiny_mce.js', 'js/tiny_mce_textareas.js'] | |
321 | ||
734b288c PP |
322 | def save_model(self, request, obj, form, change): |
323 | responsables = form.cleaned_data['responsables'] | |
324 | for user in responsables: | |
325 | user.is_staff = True | |
326 | user.save() | |
327 | ||
2094c7e5 | 328 | if not request.user.is_superuser: |
a26d89c9 | 329 | recherches = obj.recherches.exclude(user=request.user) |
b7816629 EMS |
330 | form.cleaned_data['recherches'] = \ |
331 | set(form.cleaned_data['recherches']) | set(recherches) | |
2094c7e5 | 332 | |
734b288c PP |
333 | super(BaseGroupeAdmin, self).save_model(request, obj, form, change) |
334 | ||
4a7399ee PP |
335 | def queryset(self, request): |
336 | qs = super(BaseGroupeAdmin, self).queryset(request) | |
337 | ||
b7816629 EMS |
338 | if not request.user.is_superuser \ |
339 | and not request.user.has_perm('chercheurs.change_groupechercheur'): | |
85f53a92 PP |
340 | qs = qs.filter(responsables=request.user) |
341 | ||
342 | return qs | |
4a7399ee PP |
343 | |
344 | def has_change_permission(self, request, obj=None, groupe_chercheur=False): | |
345 | ||
346 | if not obj: | |
b7816629 EMS |
347 | if request.user.responsable_groupe \ |
348 | .filter(groupe_chercheur=groupe_chercheur).count(): | |
4a7399ee PP |
349 | return True |
350 | else: | |
351 | if request.user in obj.responsables.all(): | |
352 | return True | |
353 | ||
354 | return super(BaseGroupeAdmin, self).has_change_permission(request, obj) | |
734b288c | 355 | |
2094c7e5 PP |
356 | def formfield_for_manytomany(self, db_field, request, **kwargs): |
357 | if db_field.name == "recherches" and not request.user.is_superuser: | |
358 | kwargs["queryset"] = Search.objects.filter(user=request.user) | |
359 | return db_field.formfield(**kwargs) | |
7b0b2f96 PP |
360 | |
361 | if db_field.name == "responsables": | |
362 | kwargs["queryset"] = User.objects.all().order_by('username') | |
363 | return db_field.formfield(**kwargs) | |
364 | ||
b7816629 EMS |
365 | return super(BaseGroupeAdmin, self).formfield_for_manytomany( |
366 | db_field, request, **kwargs | |
367 | ) | |
2094c7e5 PP |
368 | |
369 | ||
44e07248 | 370 | class GroupeChercheurAdmin(BaseGroupeAdmin): |
4a7399ee PP |
371 | |
372 | def has_change_permission(self, request, obj=None): | |
b7816629 EMS |
373 | return super(GroupeChercheurAdmin, self) \ |
374 | .has_change_permission(request, obj, groupe_chercheur=True) | |
4a7399ee | 375 | |
44e07248 PP |
376 | |
377 | class DomaineRechercheAdmin(BaseGroupeAdmin): | |
4a7399ee PP |
378 | |
379 | def has_change_permission(self, request, obj=None): | |
b7816629 EMS |
380 | return super(DomaineRechercheAdmin, self) \ |
381 | .has_change_permission(request, obj, groupe_chercheur=False) | |
cec3f8db | 382 | |
549417d6 PP |
383 | |
384 | class MessageAdmin(admin.ModelAdmin): | |
385 | list_filter = ('groupe',) | |
386 | ||
387 | ||
78399ad5 PP |
388 | class PublicationAdmin(admin.ModelAdmin): |
389 | search_fields = ('auteurs', 'titre', 'revue', 'editeur') | |
390 | ||
391 | ||
55ef8558 | 392 | admin.site.register(Chercheur, ChercheurAdmin) |
78399ad5 | 393 | admin.site.register(Publication, PublicationAdmin) |
cec3f8db PP |
394 | admin.site.register(GroupeChercheur, GroupeChercheurAdmin) |
395 | admin.site.register(DomaineRecherche, DomaineRechercheAdmin) | |
dca3ff65 PP |
396 | admin.site.register(AdhesionCommunaute, AdhesionCommunauteAdmin) |
397 | admin.site.register(AdhesionDomaineRecherche, AdhesionDomaineRechercheAdmin) | |
549417d6 | 398 | admin.site.register(Message, MessageAdmin) |