2563: API lister les chercheurs d'une région, partie 1
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / chercheurs / admin.py
1 # -*- coding: utf-8 -*-
2 from django.db import models
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.forms.models import BaseInlineFormSet
7 from django.http import HttpResponseRedirect
8 from django.contrib.auth.models import User
9
10 from chercheurs.models import Chercheur, ChercheurVoir, Publication, \
11 GroupeChercheur, DomaineRecherche, \
12 AdhesionGroupe, ChercheurQuerySet, \
13 AdhesionCommunaute, AdhesionDomaineRecherche, \
14 Groupe, Message
15
16 from chercheurs.utils import export
17 from savoirs.models import Search
18
19 class ChercheurAdmin(admin.ModelAdmin):
20 list_filter = ['genre']
21 alphabet_filter = 'nom'
22 alphabet_filter_table = 'chercheurs_personne'
23 DEFAULT_ALPHABET = ''
24
25 actions = ('remove_from_group', 'export_as_ods', 'export_as_csv')
26 search_fields = ('nom', 'prenom')
27
28 def lookup_allowed(self, lookup, value):
29 return lookup in ['genre', 'statut', 'membre_reseau_institutionnel',
30 'membre_instance_auf', 'discipline', 'region', 'pays',
31 'groupes', 'nord_sud'] or \
32 admin.ModelAdmin.lookup_allowed(self, lookup, value)
33
34 def remove_from_group(self, request, queryset):
35 groupe_id = request.GET.get('groupes__id__exact')
36 chercheur_ids = queryset.values_list('id', flat=True)
37 matches = AdhesionGroupe.objects.filter(groupe=groupe_id, chercheur__in=chercheur_ids)
38 matches.delete()
39 return HttpResponseRedirect(url('admin:chercheurs_chercheur_changelist') + '?groupes__id__exact=' + groupe_id)
40
41 def get_actions(self, request):
42 actions = super(ChercheurAdmin, self).get_actions(request)
43
44 # Si on filtre par groupes, offrir d'en retirer les
45 # chercheurs sélectionnés.
46 groupe_id = request.GET.get('groupes__id__exact')
47 if groupe_id:
48 groupe = Groupe.objects.get(id=groupe_id)
49 action_desc = actions['remove_from_group']
50 actions['remove_from_group'] = (action_desc[0], action_desc[1], u'Retirer du domaine de recherche « %s »' % groupe.nom)
51 else:
52 del actions['remove_from_group']
53 return actions
54
55 def queryset(self, request):
56 return ChercheurAdminQuerySet(Chercheur)
57
58 def get_object(self, request, object_id):
59 """On doit réimplémenter cette méthode à cause de ce qu'on fait avec "initial" dans la méthode queryset()."""
60 try:
61 return Chercheur.objects.get(id=object_id)
62 except Chercheur.DoesNotExist:
63 return None
64
65
66 def export_as_csv(self, request, queryset):
67 return export(queryset, 'csv')
68 export_as_csv.short_description = 'Export CSV'
69
70 def export_as_ods(self, request, queryset):
71 return export(queryset, 'ods')
72 export_as_ods.short_description = 'Export ODS'
73
74
75 class ChercheurVoirAdmin(ChercheurAdmin):
76
77 list_editable = []
78 fields = ['salutation', 'nom', 'prenom', 'courriel', 'afficher_courriel',
79 'fonction', 'date_naissance', 'sousfonction', 'telephone',
80 'adresse_postale', 'genre', 'commentaire',
81
82 'nationalite', 'statut', 'diplome', 'etablissement',
83 'etablissement_autre_nom', 'etablissement_autre_pays',
84 'attestation', 'thematique', 'mots_cles', 'discipline',
85 'theme_recherche', 'equipe_recherche', 'url_site_web',
86 'url_blog', 'url_reseau_social',
87 'membre_instance_auf', 'membre_instance_auf_nom',
88 'membre_instance_auf_fonction', 'membre_instance_auf_dates',
89 'expert_oif', 'expert_oif_details', 'expert_oif_dates',
90 'membre_association_francophone', 'membre_association_francophone_details',
91 'membre_reseau_institutionnel', 'membre_reseau_institutionnel_nom',
92 'membre_reseau_institutionnel_fonction', 'membre_reseau_institutionnel_dates',
93 'expertises_auf']
94
95 def __init__(self, model, admin_site):
96 super(ChercheurVoirAdmin, self).__init__(model, admin_site)
97 self.readonly_fields = self.fields
98
99
100 admin.site.register(ChercheurVoir, ChercheurVoirAdmin)
101
102 class ChercheurAdminQuerySet(ChercheurQuerySet):
103
104 def filter(self, *args, **kwargs):
105 """Gère des filtres supplémentaires pour l'admin.
106
107 C'est la seule façon que j'ai trouvée de contourner les mécanismes
108 de recherche de l'admin."""
109 pays = kwargs.pop('pays', None)
110 region = kwargs.pop('region', None)
111 nord_sud = kwargs.pop('nord_sud', None)
112 expert = kwargs.pop('expert', None)
113 qs = self
114 if pays is not None:
115 qs = qs.filter(Q(etablissement__pays=pays) |
116 (Q(etablissement=None) & Q(etablissement_autre_pays=pays)))
117 elif region is not None:
118 qs = qs.filter(Q(etablissement__pays__region=region) |
119 (Q(etablissement=None) & Q(etablissement_autre_pays__region=region)))
120 elif nord_sud is not None:
121 qs = qs.filter(Q(etablissement__pays__nord_sud=nord_sud) |
122 (Q(etablissement=None) & Q(etablissement_autre_pays__nord_sud=nord_sud)))
123 if expert is not None:
124 if expert in ['1', 1, True]:
125 qs = qs.exclude(expertises=None)
126 else:
127 qs = qs.filter(expertises=None)
128
129 return super(ChercheurAdminQuerySet, qs).filter(*args, **kwargs)
130
131
132 class AdhesionGroupeAdmin(admin.ModelAdmin):
133 list_filter = ('groupe','statut')
134 list_display = ('groupe', 'chercheur', 'statut')
135 list_editable = ('statut',)
136 search_fields = ('chercheur__nom', 'chercheur__prenom')
137
138 alphabet_filter = 'chercheur__nom'
139 DEFAULT_ALPHABET = ''
140
141 actions = ['assigner_cgstatut']
142
143
144 def lookup_allowed(self, lookup, value):
145 return lookup in ['chercheur__nom__istartswith'] or \
146 admin.ModelAdmin.lookup_allowed(self, lookup, value)
147
148 def queryset(self, request):
149 qs = super(AdhesionGroupeAdmin, self).queryset(request)
150
151 if not request.user.is_superuser and not request.user.has_perm('chercheurs.change_adhesiongroupe'):
152 qs = qs.filter(groupe__responsables=request.user)
153
154 return qs
155
156 def has_change_permission(self, request, obj=None):
157
158 if not obj:
159 if request.user.responsable_groupe.count():
160 return True
161 else:
162 if request.user in obj.groupe.responsables.all():
163 return True
164
165 return super(AdhesionGroupeAdmin, self).has_change_permission(request, obj)
166
167 def assigner_cgstatut(self, request, queryset):
168 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
169 return HttpResponseRedirect("/admin/assigner_%s?ids=%s" % ('cgstatut', ",".join(selected)))
170 assigner_cgstatut.short_description = u'Assigner un statut'
171
172
173 class AdhesionCommunauteAdmin(AdhesionGroupeAdmin):
174 pass
175
176
177 class AdhesionDomaineRechercheAdmin(AdhesionGroupeAdmin):
178 pass
179
180 class BaseGroupeAdmin(admin.ModelAdmin):
181 search_fields = ['nom']
182 fieldsets = (
183 (('Options générales'), {'fields': ('nom', 'url', 'liste_diffusion',
184 'bulletin', 'page_accueil')}),
185 (('Gestionnaire de communauté'), {'fields': ('responsables',)}),
186 (('Recherches prédéfinies'), {'fields': ('recherches',)}),
187 )
188
189 class Media:
190 js = ['js/tiny_mce/tiny_mce.js', 'js/tiny_mce_textareas.js']
191
192 def save_model(self, request, obj, form, change):
193 responsables = form.cleaned_data['responsables']
194 for user in responsables:
195 user.is_staff = True
196 user.save()
197
198 if not request.user.is_superuser:
199 recherches = obj.recherches.exclude(user=request.user)
200 form.cleaned_data['recherches'] = set(form.cleaned_data['recherches']) | set(recherches)
201
202 super(BaseGroupeAdmin, self).save_model(request, obj, form, change)
203
204 def queryset(self, request):
205 qs = super(BaseGroupeAdmin, self).queryset(request)
206
207 if not request.user.is_superuser and not request.user.has_perm('chercheurs.change_groupechercheur'):
208 qs = qs.filter(responsables=request.user)
209
210 return qs
211
212 def has_change_permission(self, request, obj=None, groupe_chercheur=False):
213
214 if not obj:
215 if request.user.responsable_groupe.filter(groupe_chercheur=groupe_chercheur).count():
216 return True
217 else:
218 if request.user in obj.responsables.all():
219 return True
220
221 return super(BaseGroupeAdmin, self).has_change_permission(request, obj)
222
223 def formfield_for_manytomany(self, db_field, request, **kwargs):
224 if db_field.name == "recherches" and not request.user.is_superuser:
225 kwargs["queryset"] = Search.objects.filter(user=request.user)
226 return db_field.formfield(**kwargs)
227
228 if db_field.name == "responsables":
229 kwargs["queryset"] = User.objects.all().order_by('username')
230 return db_field.formfield(**kwargs)
231
232 return super(BaseGroupeAdmin, self).formfield_for_manytomany(db_field, request, **kwargs)
233
234
235 class GroupeChercheurAdmin(BaseGroupeAdmin):
236
237 def has_change_permission(self, request, obj=None):
238 return super(GroupeChercheurAdmin, self).has_change_permission(request, obj, groupe_chercheur=True)
239
240
241 class DomaineRechercheAdmin(BaseGroupeAdmin):
242
243 def has_change_permission(self, request, obj=None):
244 return super(DomaineRechercheAdmin, self).has_change_permission(request, obj, groupe_chercheur=False)
245
246
247 class MessageAdmin(admin.ModelAdmin):
248 list_filter = ('groupe',)
249
250
251 class PublicationAdmin(admin.ModelAdmin):
252 search_fields = ('auteurs', 'titre', 'revue', 'editeur')
253
254
255 admin.site.register(Chercheur, ChercheurAdmin)
256 admin.site.register(Publication, PublicationAdmin)
257 admin.site.register(GroupeChercheur, GroupeChercheurAdmin)
258 admin.site.register(DomaineRecherche, DomaineRechercheAdmin)
259 admin.site.register(AdhesionCommunaute, AdhesionCommunauteAdmin)
260 admin.site.register(AdhesionDomaineRecherche, AdhesionDomaineRechercheAdmin)
261 admin.site.register(Message, MessageAdmin)
262