9efa226233b7109a78557e336efa2e90768c9774
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / chercheurs / admin.py
1 # -*- coding: utf-8 -*-
2 from auf.django.references import models as ref
3 from django.db.models import Q
4 from django.contrib import admin
5 from django.core.urlresolvers import reverse as url
6 from django.http import HttpResponseRedirect
7 from django.contrib.auth.models import User
8
9 from chercheurs.models import Chercheur, ChercheurVoir, Publication, \
10 GroupeChercheur, DomaineRecherche, \
11 AdhesionGroupe, ChercheurQuerySet, \
12 AdhesionCommunaute, AdhesionDomaineRecherche, \
13 Groupe, Message
14 from chercheurs.utils import export
15 from savoirs.models import Search
16
17
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):
127 return queryset.filter(groupes=self.value())
128
129
130 class DomaineRechercheListFilter(admin.SimpleListFilter):
131 title = 'domaine de recherche'
132 parameter_name = 'domaine_recherche'
133
134 def lookups(self, request, model_admin):
135 return (
136 (str(id), nom)
137 for id, nom in DomaineRecherche.objects.values_list('id', 'nom')
138 )
139
140 def queryset(self, request, queryset):
141 return queryset.filter(groupes=self.value())
142
143
144 class ChercheurAdmin(admin.ModelAdmin):
145 list_filter = (
146 'genre', 'statut', 'membre_reseau_institutionnel',
147 'membre_instance_auf', 'discipline', RegionListFilter,
148 NordSudListFilter, PaysListFilter, GroupeChercheursListFilter,
149 DomaineRechercheListFilter, ExpertListFilter
150 )
151 alphabet_filter = 'nom'
152 alphabet_filter_table = 'chercheurs_personne'
153 DEFAULT_ALPHABET = ''
154
155 actions = ('remove_from_group', 'export_as_ods', 'export_as_csv')
156 search_fields = ('nom', 'prenom')
157
158 exclude = ('user',)
159
160 def lookup_allowed(self, lookup, value):
161 return lookup in ['genre', 'statut', 'membre_reseau_institutionnel',
162 'membre_instance_auf', 'discipline', 'region',
163 'pays', 'groupes', 'nord_sud'] or \
164 admin.ModelAdmin.lookup_allowed(self, lookup, value)
165
166 def remove_from_group(self, request, queryset):
167 groupe_id = request.GET.get('groupes__id__exact')
168 chercheur_ids = queryset.values_list('id', flat=True)
169 matches = AdhesionGroupe.objects.filter(
170 groupe=groupe_id, chercheur__in=chercheur_ids
171 )
172 matches.delete()
173 return HttpResponseRedirect(
174 url('admin:chercheurs_chercheur_changelist') +
175 '?groupes__id__exact=' + groupe_id
176 )
177
178 def get_actions(self, request):
179 actions = super(ChercheurAdmin, self).get_actions(request)
180
181 # Si on filtre par groupes, offrir d'en retirer les
182 # chercheurs sélectionnés.
183 groupe_id = request.GET.get('groupes__id__exact')
184 if groupe_id:
185 groupe = Groupe.objects.get(id=groupe_id)
186 action_desc = actions['remove_from_group']
187 actions['remove_from_group'] = (
188 action_desc[0],
189 action_desc[1],
190 u'Retirer du domaine de recherche « %s »' % groupe.nom
191 )
192 else:
193 del actions['remove_from_group']
194 return actions
195
196 def queryset(self, request):
197 return ChercheurAdminQuerySet(Chercheur).filter(actif=True)
198
199 def get_object(self, request, object_id):
200 """
201 On doit réimplémenter cette méthode à cause de ce qu'on fait avec
202 ``initial`` dans la méthode queryset().
203 """
204 try:
205 return Chercheur.objects.get(id=object_id)
206 except Chercheur.DoesNotExist:
207 return None
208
209 def has_add_permission(self, request, obj=None):
210 return False
211
212 def export_as_csv(self, request, queryset):
213 return export(queryset, 'csv')
214 export_as_csv.short_description = 'Export CSV'
215
216 def export_as_ods(self, request, queryset):
217 return export(queryset, 'ods')
218 export_as_ods.short_description = 'Export ODS'
219
220
221 class ChercheurVoirAdmin(ChercheurAdmin):
222
223 list_editable = []
224 fields = ['salutation', 'nom', 'prenom', 'courriel',
225 'afficher_courriel', 'fonction', 'date_naissance',
226 'sousfonction', 'telephone', 'adresse_postale', 'genre',
227 'commentaire', 'nationalite', 'statut', 'diplome',
228 'etablissement', 'etablissement_autre_nom',
229 'etablissement_autre_pays', 'attestation', 'thematique',
230 'mots_cles', 'discipline', 'theme_recherche',
231 'equipe_recherche', 'url_site_web', 'url_blog',
232 'url_reseau_social', 'membre_instance_auf',
233 'membre_instance_auf_nom', 'membre_instance_auf_fonction',
234 'membre_instance_auf_dates', 'expert_oif',
235 'expert_oif_details', 'expert_oif_dates',
236 'membre_association_francophone',
237 'membre_association_francophone_details',
238 'membre_reseau_institutionnel',
239 'membre_reseau_institutionnel_nom',
240 'membre_reseau_institutionnel_fonction',
241 'membre_reseau_institutionnel_dates', 'expertises_auf']
242
243 def __init__(self, model, admin_site):
244 super(ChercheurVoirAdmin, self).__init__(model, admin_site)
245 self.readonly_fields = self.fields
246
247 admin.site.register(ChercheurVoir, ChercheurVoirAdmin)
248
249
250 class ChercheurAdminQuerySet(ChercheurQuerySet):
251
252 def delete(self):
253 self.update(actif=False)
254
255
256 class AdhesionGroupeAdmin(admin.ModelAdmin):
257 list_filter = ('groupe', 'statut')
258 list_display = ('groupe', 'chercheur', 'statut')
259 list_editable = ('statut',)
260 search_fields = ('chercheur__nom', 'chercheur__prenom')
261
262 alphabet_filter = 'chercheur__nom'
263 DEFAULT_ALPHABET = ''
264
265 actions = ['assigner_cgstatut']
266
267 def lookup_allowed(self, lookup, value):
268 return lookup in ['chercheur__nom__istartswith'] or \
269 admin.ModelAdmin.lookup_allowed(self, lookup, value)
270
271 def queryset(self, request):
272 qs = super(AdhesionGroupeAdmin, self).queryset(request)
273
274 if not request.user.is_superuser \
275 and not request.user.has_perm('chercheurs.change_adhesiongroupe'):
276 qs = qs.filter(groupe__responsables=request.user)
277
278 return qs
279
280 def has_change_permission(self, request, obj=None):
281
282 if not obj:
283 if request.user.responsable_groupe.count():
284 return True
285 else:
286 if request.user in obj.groupe.responsables.all():
287 return True
288
289 return super(AdhesionGroupeAdmin, self) \
290 .has_change_permission(request, obj)
291
292 def assigner_cgstatut(self, request, queryset):
293 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
294 return HttpResponseRedirect(
295 "/admin/assigner_%s?ids=%s" % ('cgstatut', ",".join(selected))
296 )
297 assigner_cgstatut.short_description = u'Assigner un statut'
298
299
300 class AdhesionCommunauteAdmin(AdhesionGroupeAdmin):
301 pass
302
303
304 class AdhesionDomaineRechercheAdmin(AdhesionGroupeAdmin):
305 pass
306
307
308 class BaseGroupeAdmin(admin.ModelAdmin):
309 search_fields = ['nom']
310 fieldsets = (
311 (('Options générales'), {'fields': ('nom', 'url', 'liste_diffusion',
312 'bulletin', 'page_accueil')}),
313 (('Gestionnaire de communauté'), {'fields': ('responsables',)}),
314 (('Recherches prédéfinies'), {'fields': ('recherches',)}),
315 )
316
317 class Media:
318 js = ['js/tiny_mce/tiny_mce.js', 'js/tiny_mce_textareas.js']
319
320 def save_model(self, request, obj, form, change):
321 responsables = form.cleaned_data['responsables']
322 for user in responsables:
323 user.is_staff = True
324 user.save()
325
326 if not request.user.is_superuser:
327 recherches = obj.recherches.exclude(user=request.user)
328 form.cleaned_data['recherches'] = \
329 set(form.cleaned_data['recherches']) | set(recherches)
330
331 super(BaseGroupeAdmin, self).save_model(request, obj, form, change)
332
333 def queryset(self, request):
334 qs = super(BaseGroupeAdmin, self).queryset(request)
335
336 if not request.user.is_superuser \
337 and not request.user.has_perm('chercheurs.change_groupechercheur'):
338 qs = qs.filter(responsables=request.user)
339
340 return qs
341
342 def has_change_permission(self, request, obj=None, groupe_chercheur=False):
343
344 if not obj:
345 if request.user.responsable_groupe \
346 .filter(groupe_chercheur=groupe_chercheur).count():
347 return True
348 else:
349 if request.user in obj.responsables.all():
350 return True
351
352 return super(BaseGroupeAdmin, self).has_change_permission(request, obj)
353
354 def formfield_for_manytomany(self, db_field, request, **kwargs):
355 if db_field.name == "recherches" and not request.user.is_superuser:
356 kwargs["queryset"] = Search.objects.filter(user=request.user)
357 return db_field.formfield(**kwargs)
358
359 if db_field.name == "responsables":
360 kwargs["queryset"] = User.objects.all().order_by('username')
361 return db_field.formfield(**kwargs)
362
363 return super(BaseGroupeAdmin, self).formfield_for_manytomany(
364 db_field, request, **kwargs
365 )
366
367
368 class GroupeChercheurAdmin(BaseGroupeAdmin):
369
370 def has_change_permission(self, request, obj=None):
371 return super(GroupeChercheurAdmin, self) \
372 .has_change_permission(request, obj, groupe_chercheur=True)
373
374
375 class DomaineRechercheAdmin(BaseGroupeAdmin):
376
377 def has_change_permission(self, request, obj=None):
378 return super(DomaineRechercheAdmin, self) \
379 .has_change_permission(request, obj, groupe_chercheur=False)
380
381
382 class MessageAdmin(admin.ModelAdmin):
383 list_filter = ('groupe',)
384
385
386 class PublicationAdmin(admin.ModelAdmin):
387 search_fields = ('auteurs', 'titre', 'revue', 'editeur')
388
389
390 admin.site.register(Chercheur, ChercheurAdmin)
391 admin.site.register(Publication, PublicationAdmin)
392 admin.site.register(GroupeChercheur, GroupeChercheurAdmin)
393 admin.site.register(DomaineRecherche, DomaineRechercheAdmin)
394 admin.site.register(AdhesionCommunaute, AdhesionCommunauteAdmin)
395 admin.site.register(AdhesionDomaineRecherche, AdhesionDomaineRechercheAdmin)
396 admin.site.register(Message, MessageAdmin)