[#3416] Ressources (edition) Permet d'éditer les champs
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / savoirs / admin.py
1 # -*- encoding: utf-8 -*-
2 import operator
3
4 from auf.django.references import models as ref
5 from django import forms
6 from django.core.urlresolvers import reverse as url
7 from django.contrib import admin
8 from django.contrib.auth.admin import UserAdmin
9 from django.contrib.auth.models import User
10 from django.db.models import Q
11 from django.db.models.query import QuerySet
12 from django.http import HttpResponseRedirect
13
14 from auf_savoirs_en_partage.savoirs.globals import META
15 from auf_savoirs_en_partage.savoirs.models import \
16 SourceActualite, Actualite, ActualiteVoir, \
17 Evenement, EvenementVoir, Record, RecordEdit, \
18 RecordCategorie, ListSet, HarvestLog, Profile, PageStatique
19
20
21 class ListSetListFilter(admin.RelatedFieldListFilter):
22 """
23 Filtre custom automatiquement lié à un field nommé 'listsets'. Il a pour
24 but de s'afficher lorsqu'un server a déjà été présélectionné. Dans ce
25 cas, il affiche une liste qui contient les listsets de ce server.
26 """
27 def __init__(self, field, request, params, model, model_admin, field_path):
28 super(ListSetListFilter, self).__init__(
29 field, request, params, model, model_admin, field_path
30 )
31 self.server_name = request.GET.get('server', None)
32
33 def has_output(self):
34 return self.server_name is not None
35
36
37 class AllRegionsListFilter(admin.SimpleListFilter):
38 """
39 Filtre qui offre aussi les régions inactives dans ses choix.
40 """
41 title = u'région'
42 parameter_name = 'regions'
43
44 def lookups(self, request, model_admin):
45 return [(r.id, r.nom) for r in ref.Region.avec_inactifs.all()]
46
47 def queryset(self, request, queryset):
48 return queryset.filter(regions=self.value())
49
50
51 class RecordAdminQuerySet(QuerySet):
52
53 def filter(self, *args, **kwargs):
54 """Gère des filtres supplémentaires pour l'admin.
55
56 C'est la seule façon que j'ai trouvée de contourner les mécanismes
57 de recherche de l'admin."""
58 search = kwargs.pop('admin_search', None)
59 search_titre = kwargs.pop('admin_search_titre', None)
60 search_sujet = kwargs.pop('admin_search_sujet', None)
61 search_description = kwargs.pop('admin_search_description', None)
62 search_auteur = kwargs.pop('admin_search_auteur', None)
63
64 if search:
65 qs = self
66 search_all = not (search_titre or search_description or
67 search_sujet or search_auteur)
68 fields = []
69 if search_titre or search_all:
70 fields += ['title', 'alt_title']
71 if search_description or search_all:
72 fields += ['description', 'abstract']
73 if search_sujet or search_all:
74 fields += ['subject']
75 if search_auteur or search_all:
76 fields += ['creator', 'contributor']
77
78 for bit in search.split():
79 or_queries = [Q(**{field + '__icontains': bit})
80 for field in fields]
81 qs = qs.filter(reduce(operator.or_, or_queries))
82
83 if args or kwargs:
84 qs = super(RecordAdminQuerySet, qs).filter(*args, **kwargs)
85 return qs
86 else:
87 return super(RecordAdminQuerySet, self).filter(*args, **kwargs)
88
89
90 class RecordAdmin(admin.ModelAdmin):
91 fields = ('server', 'title', 'creator', 'description', 'modified',
92 'identifier', 'uri', 'source', 'contributor', 'publisher',
93 'type', 'format', 'language', 'categorie', 'disciplines',
94 'thematiques', 'pays', 'regions', 'validated')
95
96 list_filter = (
97 'validated', 'server', ('listsets', ListSetListFilter), 'pays',
98 AllRegionsListFilter, 'disciplines', 'thematiques', 'categorie'
99 )
100 list_display = (
101 'title', 'subject', 'uri_display', 'creator', 'categorie',
102 'est_complet', 'validated'
103 )
104 list_editable = ('validated',)
105 list_per_page = 25
106
107 actions = ('assigner_pays', 'assigner_regions', 'assigner_disciplines',
108 'assigner_thematiques', 'assigner_categorie')
109
110 def __init__(self, *args, **kwargs):
111 """
112 Surcharge l'initialisation pour définir les champs de recherche
113 dynamiquement, et les champs en lecture seule uniquement.
114 """
115 self.readonly_fields = META.keys()
116 self.readonly_fields.append('listsets')
117 super(RecordAdmin, self).__init__(*args, **kwargs)
118
119 def queryset(self, request):
120 return RecordAdminQuerySet(Record)
121
122 # Présentation de l'information
123
124 def est_complet(self, obj):
125 v = obj.est_complet()
126 return '<img src="/static/admin/img/icon-%s.gif" alt="%d"/>' % (
127 ('no', 'yes')[v], v
128 )
129 est_complet.allow_tags = True
130 est_complet.short_description = u'complet'
131
132 def uri_display(self, obj):
133 return "<a target='_blank' href='%s'>%s</a>" % (obj.uri, obj.uri)
134 uri_display.allow_tags = True
135 uri_display.short_description = u'lien'
136
137 def description_display(self, obj):
138 max = 140
139 if obj.description is not None and len(obj.description) > max:
140 return "%s..." % obj.description[:max]
141 else:
142 return obj.description
143 description_display.short_description = u'description'
144
145 # Actions
146
147 def assigner_pays(self, request, queryset):
148 selected = queryset.values_list('id', flat=True)
149 selected = ",".join("%s" % val for val in selected)
150 return HttpResponseRedirect(
151 "/admin/assigner_%s?ids=%s" % ('pays', selected)
152 )
153 assigner_pays.short_description = u'Assigner des pays'
154
155 def assigner_regions(self, request, queryset):
156 selected = queryset.values_list('id', flat=True)
157 selected = ",".join("%s" % val for val in selected)
158 return HttpResponseRedirect(url(
159 'assigner_regions',
160 kwargs={'app_name': 'savoirs', 'model_name': 'record'}
161 ) + '?ids=' + selected)
162 assigner_regions.short_description = u'Assigner des régions'
163
164 def assigner_thematiques(self, request, queryset):
165 selected = queryset.values_list('id', flat=True)
166 selected = ",".join("%s" % val for val in selected)
167 return HttpResponseRedirect(
168 "/admin/assigner_%s?ids=%s" % ('thematiques', selected)
169 )
170 assigner_thematiques.short_description = u'Assigner des thématiques'
171
172 def assigner_disciplines(self, request, queryset):
173 selected = queryset.values_list('id', flat=True)
174 selected = ",".join("%s" % val for val in selected)
175 return HttpResponseRedirect(url(
176 'assigner_disciplines',
177 kwargs={'app_name': 'savoirs', 'model_name': 'record'}
178 ) + '?ids=' + selected)
179 assigner_disciplines.short_description = u'Assigner des disciplines'
180
181 def assigner_categorie(self, request, queryset):
182 selected = queryset.values_list('id', flat=True)
183 selected = ",".join("%s" % val for val in selected)
184 return HttpResponseRedirect(
185 "/admin/assigner_%s?ids=%s" % ('categorie', selected)
186 )
187 assigner_categorie.short_description = u'Assigner une catégorie'
188
189 admin.site.register(Record, RecordAdmin)
190
191
192 class RecordEditAdmin(RecordAdmin):
193 list_editable = ()
194 change_list_template = "admin/savoirs/record/change_list.html"
195
196 def __init__(self, model, admin_site):
197 super(RecordEditAdmin, self).__init__(model, admin_site)
198 self.readonly_fields = ()
199
200 def get_actions(self, request):
201 actions = super(RecordEditAdmin, self).get_actions(request)
202 del actions['assigner_pays']
203 del actions['assigner_regions']
204 del actions['assigner_disciplines']
205 del actions['assigner_thematiques']
206 del actions['assigner_categorie']
207
208 return actions
209
210 admin.site.register(RecordEdit, RecordEditAdmin)
211
212
213 class ListSetAdmin(admin.ModelAdmin):
214 fields = ('spec', 'name', 'server', 'validated')
215 list_display = fields
216 readonly_fields = ('spec', 'name', 'server')
217 list_filter = ('server',)
218
219 admin.site.register(ListSet, ListSetAdmin)
220
221
222 class HarvestLogAdmin(admin.ModelAdmin):
223 fields = ('context', 'name', 'added', 'updated', 'processed', 'record')
224 list_display = fields + ('date',)
225 admin_order_fields = ('date',)
226 search_fields = (
227 'context', 'name', 'added', 'updated', 'processed', 'record__title'
228 )
229 readonly_fields = fields
230 list_filter = ('context',)
231
232 admin.site.register(HarvestLog, HarvestLogAdmin)
233
234
235 class ProfileInline(admin.TabularInline):
236 model = Profile
237 fk_name = 'user'
238 max_num = 1
239
240
241 class UserProfileAdmin(UserAdmin):
242 inlines = (ProfileInline,)
243
244 admin.site.unregister(User)
245 admin.site.register(User, UserProfileAdmin)
246
247
248 class ActualiteAdmin(admin.ModelAdmin):
249 list_filter = ('visible', 'disciplines', AllRegionsListFilter)
250 list_display = ('titre', 'source', 'date', 'visible')
251 list_editable = ('visible',)
252 search_fields = ('titre', 'texte')
253 actions = (
254 'rendre_visible', 'rendre_invisible', 'assigner_regions',
255 'assigner_disciplines'
256 )
257
258 def queryset(self, request):
259 return Actualite.all_objects.get_query_set()
260
261 # actions
262 def rendre_visible(self, request, queryset):
263 selected = queryset.values_list('id', flat=True)
264 selected = ",".join("%s" % val for val in selected)
265 return HttpResponseRedirect(
266 "/admin/confirmation/%s/%s?ids=%s" %
267 ('actualite', 'visible', selected)
268 )
269
270 def rendre_invisible(self, request, queryset):
271 selected = queryset.values_list('id', flat=True)
272 selected = ",".join("%s" % val for val in selected)
273 return HttpResponseRedirect(
274 "/admin/confirmation/%s/%s?ids=%s" %
275 ('actualite', 'invisible', selected)
276 )
277
278 def assigner_regions(self, request, queryset):
279 selected = queryset.values_list('id', flat=True)
280 selected = ",".join("%s" % val for val in selected)
281 return HttpResponseRedirect(url(
282 'assigner_regions',
283 kwargs={'app_name': 'savoirs', 'model_name': 'actualite'}
284 ) + '?ids=' + selected)
285 assigner_regions.short_description = u'Assigner des régions'
286
287 def assigner_disciplines(self, request, queryset):
288 selected = queryset.values_list('id', flat=True)
289 selected = ",".join("%s" % val for val in selected)
290 return HttpResponseRedirect(url(
291 'assigner_disciplines',
292 kwargs={'app_name': 'savoirs', 'model_name': 'actualite'}
293 ) + '?ids=' + selected)
294 assigner_disciplines.short_description = u'Assigner des disciplines'
295
296 admin.site.register(Actualite, ActualiteAdmin)
297
298
299 class ActualiteVoirAdmin(ActualiteAdmin):
300
301 actions = None
302 list_editable = ()
303 fields = (
304 'titre', 'texte', 'url', 'date', 'visible', 'ancienid', 'source',
305 'disciplines', 'regions'
306 )
307
308 def __init__(self, model, admin_site):
309 super(ActualiteVoirAdmin, self).__init__(model, admin_site)
310 self.readonly_fields = self.fields
311
312
313 admin.site.register(ActualiteVoir, ActualiteVoirAdmin)
314
315
316 class SourceActualiteAdmin(admin.ModelAdmin):
317 actions = ('update_sources',)
318 list_display = ('nom', 'url', 'type')
319 list_filter = ('type',)
320
321 def update_sources(self, request, queryset):
322 for source in queryset:
323 source.update()
324 update_sources.short_description = u'Mettre à jour les fils sélectionnés'
325
326 admin.site.register(SourceActualite, SourceActualiteAdmin)
327
328
329 class EvenementAdminForm(forms.ModelForm):
330 mots_cles = forms.CharField(label='Mots-clés', required=False)
331
332 class Meta:
333 model = Evenement
334
335 def clean(self,):
336 cleaned_data = self.cleaned_data
337 debut = cleaned_data.get("debut")
338 fin = cleaned_data.get("fin")
339 if debut and fin and debut > fin:
340 raise forms.ValidationError(
341 "La date de fin ne doit pas être antérieure à la date de début"
342 )
343 return cleaned_data
344
345
346 class EvenementAdmin(admin.ModelAdmin):
347 form = EvenementAdminForm
348 list_filter = (
349 'approuve', AllRegionsListFilter, 'discipline', 'discipline_secondaire'
350 )
351 list_display = ('titre', 'debut', 'fin', 'ville', 'pays', 'approuve')
352 fields = ('titre', 'discipline', 'discipline_secondaire', 'mots_cles',
353 'type', 'adresse', 'ville', 'pays', 'fuseau', 'debut', 'fin',
354 'piece_jointe', 'regions', 'description', 'prenom', 'nom',
355 'courriel', 'url', 'approuve')
356 search_fields = ('titre', 'description')
357 actions = ('assigner_regions', 'assigner_disciplines')
358
359 def queryset(self, request):
360 return Evenement.all_objects.get_query_set()
361
362 def assigner_regions(self, request, queryset):
363 selected = queryset.values_list('id', flat=True)
364 selected = ",".join("%s" % val for val in selected)
365 return HttpResponseRedirect(url(
366 'assigner_regions',
367 kwargs={'app_name': 'savoirs', 'model_name': 'evenement'}
368 ) + '?ids=' + selected)
369 assigner_regions.short_description = u'Assigner des régions'
370
371 def assigner_disciplines(self, request, queryset):
372 selected = queryset.values_list('id', flat=True)
373 selected = ",".join("%s" % val for val in selected)
374 return HttpResponseRedirect(url(
375 'assigner_disciplines',
376 kwargs={'app_name': 'savoirs', 'model_name': 'evenement'}
377 ) + '?ids=' + selected)
378 assigner_disciplines.short_description = u'Assigner des disciplines'
379
380 admin.site.register(Evenement, EvenementAdmin)
381
382
383 class EvenementVoirAdmin(EvenementAdmin):
384
385 actions = None
386 list_editable = ()
387
388 def __init__(self, model, admin_site):
389 super(EvenementVoirAdmin, self).__init__(model, admin_site)
390 self.readonly_fields = self.fields
391
392 admin.site.register(EvenementVoir, EvenementVoirAdmin)
393
394
395 class PageStatiqueAdmin(admin.ModelAdmin):
396 list_display = ('titre', 'id')
397 list_display_links = ('titre', 'id')
398
399 class Media:
400 js = ('js/tiny_mce/tiny_mce.js', 'js/tiny_mce_textareas.js')
401
402 admin.site.register(PageStatique, PageStatiqueAdmin)
403
404
405 admin.site.register(RecordCategorie)