Optimisation de la requête des ressources valides
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / chercheurs / admin.py
CommitLineData
6f8d521e 1# -*- coding: utf-8 -*-
44a788a6 2from auf.django.references import models as ref
6f8d521e 3from django.db.models import Q
cbae0173 4from django.contrib import admin
55ef8558 5from django.core.urlresolvers import reverse as url
55ef8558 6from django.http import HttpResponseRedirect
7b0b2f96 7from django.contrib.auth.models import User
cbae0173 8
4d42b353
PP
9from chercheurs.models import Chercheur, ChercheurVoir, ChercheurInactif, \
10 Publication, GroupeChercheur, DomaineRecherche, \
dca3ff65
PP
11 AdhesionGroupe, ChercheurQuerySet, \
12 AdhesionCommunaute, AdhesionDomaineRecherche, \
549417d6 13 Groupe, Message
66386d77 14from chercheurs.utils import export
2094c7e5 15from savoirs.models import Search
6f8d521e 16
b7816629 17
44a788a6
EMS
18class 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
41class 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
62class 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
82class 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
99class 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
116class 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
131class 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 146class 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
223class 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
249admin.site.register(ChercheurVoir, ChercheurVoirAdmin)
250
4d42b353
PP
251class ChercheurInactifAdmin(ChercheurAdmin):
252
253 list_editable = []
254
255 def queryset(self, request):
256 return self.model.objects.get_query_set().filter(actif=False)
257
258 def get_object(self, request, object_id):
259 """
260 On doit réimplémenter cette méthode à cause de ce qu'on fait avec
261 ``initial`` dans la méthode queryset().
262 """
263 try:
264 return ChercheurInactif.objects.get(id=object_id)
265 except ChercheurInactif.DoesNotExist:
266 return None
267
268admin.site.register(ChercheurInactif, ChercheurInactifAdmin)
269
b7816629 270
6f8d521e
EMS
271class ChercheurAdminQuerySet(ChercheurQuerySet):
272
120891b9
PP
273 def delete(self):
274 self.update(actif=False)
275
cec3f8db 276
18407f73 277class AdhesionGroupeAdmin(admin.ModelAdmin):
b7816629 278 list_filter = ('groupe', 'statut')
61c05759
PP
279 list_display = ('groupe', 'chercheur', 'statut')
280 list_editable = ('statut',)
5cba4157 281 search_fields = ('chercheur__nom', 'chercheur__prenom')
4ef9751d 282
b0db5c3e
PP
283 alphabet_filter = 'chercheur__nom'
284 DEFAULT_ALPHABET = ''
285
1fd4a630
PP
286 actions = ['assigner_cgstatut']
287
b0db5c3e
PP
288 def lookup_allowed(self, lookup, value):
289 return lookup in ['chercheur__nom__istartswith'] or \
290 admin.ModelAdmin.lookup_allowed(self, lookup, value)
291
4ef9751d 292 def queryset(self, request):
18407f73 293 qs = super(AdhesionGroupeAdmin, self).queryset(request)
4ef9751d 294
b7816629
EMS
295 if not request.user.is_superuser \
296 and not request.user.has_perm('chercheurs.change_adhesiongroupe'):
4ef9751d
PP
297 qs = qs.filter(groupe__responsables=request.user)
298
299 return qs
300
301 def has_change_permission(self, request, obj=None):
302
303 if not obj:
304 if request.user.responsable_groupe.count():
305 return True
306 else:
307 if request.user in obj.groupe.responsables.all():
308 return True
309
b7816629
EMS
310 return super(AdhesionGroupeAdmin, self) \
311 .has_change_permission(request, obj)
4ef9751d 312
1fd4a630
PP
313 def assigner_cgstatut(self, request, queryset):
314 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
b7816629
EMS
315 return HttpResponseRedirect(
316 "/admin/assigner_%s?ids=%s" % ('cgstatut', ",".join(selected))
317 )
1fd4a630
PP
318 assigner_cgstatut.short_description = u'Assigner un statut'
319
6d5279ff 320
dca3ff65
PP
321class AdhesionCommunauteAdmin(AdhesionGroupeAdmin):
322 pass
323
324
325class AdhesionDomaineRechercheAdmin(AdhesionGroupeAdmin):
326 pass
327
b7816629 328
44e07248 329class BaseGroupeAdmin(admin.ModelAdmin):
b803eb99 330 search_fields = ['nom']
6d5279ff 331 fieldsets = (
0c0d997c
PP
332 (('Options générales'), {'fields': ('nom', 'url', 'liste_diffusion',
333 'bulletin', 'page_accueil')}),
34d0147e 334 (('Gestionnaire de communauté'), {'fields': ('responsables',)}),
2094c7e5 335 (('Recherches prédéfinies'), {'fields': ('recherches',)}),
6d5279ff 336 )
cec3f8db 337
0c0d997c
PP
338 class Media:
339 js = ['js/tiny_mce/tiny_mce.js', 'js/tiny_mce_textareas.js']
340
734b288c
PP
341 def save_model(self, request, obj, form, change):
342 responsables = form.cleaned_data['responsables']
343 for user in responsables:
344 user.is_staff = True
345 user.save()
346
2094c7e5 347 if not request.user.is_superuser:
a26d89c9 348 recherches = obj.recherches.exclude(user=request.user)
b7816629
EMS
349 form.cleaned_data['recherches'] = \
350 set(form.cleaned_data['recherches']) | set(recherches)
2094c7e5 351
734b288c
PP
352 super(BaseGroupeAdmin, self).save_model(request, obj, form, change)
353
4a7399ee
PP
354 def queryset(self, request):
355 qs = super(BaseGroupeAdmin, self).queryset(request)
356
b7816629
EMS
357 if not request.user.is_superuser \
358 and not request.user.has_perm('chercheurs.change_groupechercheur'):
85f53a92
PP
359 qs = qs.filter(responsables=request.user)
360
361 return qs
4a7399ee
PP
362
363 def has_change_permission(self, request, obj=None, groupe_chercheur=False):
364
365 if not obj:
b7816629
EMS
366 if request.user.responsable_groupe \
367 .filter(groupe_chercheur=groupe_chercheur).count():
4a7399ee
PP
368 return True
369 else:
370 if request.user in obj.responsables.all():
371 return True
372
373 return super(BaseGroupeAdmin, self).has_change_permission(request, obj)
734b288c 374
2094c7e5
PP
375 def formfield_for_manytomany(self, db_field, request, **kwargs):
376 if db_field.name == "recherches" and not request.user.is_superuser:
377 kwargs["queryset"] = Search.objects.filter(user=request.user)
378 return db_field.formfield(**kwargs)
7b0b2f96
PP
379
380 if db_field.name == "responsables":
381 kwargs["queryset"] = User.objects.all().order_by('username')
382 return db_field.formfield(**kwargs)
383
b7816629
EMS
384 return super(BaseGroupeAdmin, self).formfield_for_manytomany(
385 db_field, request, **kwargs
386 )
2094c7e5
PP
387
388
44e07248 389class GroupeChercheurAdmin(BaseGroupeAdmin):
4a7399ee
PP
390
391 def has_change_permission(self, request, obj=None):
b7816629
EMS
392 return super(GroupeChercheurAdmin, self) \
393 .has_change_permission(request, obj, groupe_chercheur=True)
4a7399ee 394
44e07248
PP
395
396class DomaineRechercheAdmin(BaseGroupeAdmin):
4a7399ee
PP
397
398 def has_change_permission(self, request, obj=None):
b7816629
EMS
399 return super(DomaineRechercheAdmin, self) \
400 .has_change_permission(request, obj, groupe_chercheur=False)
cec3f8db 401
549417d6
PP
402
403class MessageAdmin(admin.ModelAdmin):
404 list_filter = ('groupe',)
405
406
78399ad5
PP
407class PublicationAdmin(admin.ModelAdmin):
408 search_fields = ('auteurs', 'titre', 'revue', 'editeur')
409
410
55ef8558 411admin.site.register(Chercheur, ChercheurAdmin)
78399ad5 412admin.site.register(Publication, PublicationAdmin)
cec3f8db
PP
413admin.site.register(GroupeChercheur, GroupeChercheurAdmin)
414admin.site.register(DomaineRecherche, DomaineRechercheAdmin)
dca3ff65
PP
415admin.site.register(AdhesionCommunaute, AdhesionCommunauteAdmin)
416admin.site.register(AdhesionDomaineRecherche, AdhesionDomaineRechercheAdmin)
549417d6 417admin.site.register(Message, MessageAdmin)