Ajout de search fields
[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="/admin_media/img/admin/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 = self.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_thematiques']
204 del actions['assigner_categorie']
205
206 return actions
207
208 def assigner_disciplines(self, request, queryset):
209 selected = queryset.values_list('id', flat=True)
210 selected = ",".join("%s" % val for val in selected)
211 return HttpResponseRedirect(url(
212 'assigner_disciplines',
213 kwargs={'app_name': 'savoirs', 'model_name': 'recordedit'}
214 ) + '?ids=' + selected)
215 assigner_disciplines.short_description = u'Assigner des disciplines'
216
217 def assigner_regions(self, request, queryset):
218 selected = queryset.values_list('id', flat=True)
219 selected = ",".join("%s" % val for val in selected)
220 return HttpResponseRedirect(url(
221 'assigner_regions',
222 kwargs={'app_name': 'savoirs', 'model_name': 'recordedit'}
223 ) + '?ids=' + selected)
224 assigner_regions.short_description = u'Assigner des régions'
225
226 admin.site.register(RecordEdit, RecordEditAdmin)
227
228
229 class ListSetAdmin(admin.ModelAdmin):
230 fields = ('spec', 'name', 'server', 'validated')
231 list_display = fields
232 readonly_fields = ('spec', 'name', 'server')
233 list_filter = ('server',)
234
235 admin.site.register(ListSet, ListSetAdmin)
236
237
238 class HarvestLogAdmin(admin.ModelAdmin):
239 fields = ('context', 'name', 'added', 'updated', 'processed', 'record')
240 list_display = fields + ('date',)
241 admin_order_fields = ('date',)
242 search_fields = (
243 'context', 'name', 'added', 'updated', 'processed', 'record__title'
244 )
245 readonly_fields = fields
246 list_filter = ('context',)
247
248 admin.site.register(HarvestLog, HarvestLogAdmin)
249
250
251 class ProfileInline(admin.TabularInline):
252 model = Profile
253 fk_name = 'user'
254 max_num = 1
255
256
257 class UserProfileAdmin(UserAdmin):
258 inlines = (ProfileInline,)
259
260 admin.site.unregister(User)
261 admin.site.register(User, UserProfileAdmin)
262
263
264 class ActualiteAdmin(admin.ModelAdmin):
265 list_filter = ('visible', 'disciplines', AllRegionsListFilter)
266 list_display = ('titre', 'source', 'date', 'visible')
267 list_editable = ('visible',)
268 search_fields = ('titre', 'texte')
269 actions = (
270 'rendre_visible', 'rendre_invisible', 'assigner_regions',
271 'assigner_disciplines'
272 )
273
274 def queryset(self, request):
275 return Actualite.all_objects.get_query_set()
276
277 # actions
278 def rendre_visible(self, request, queryset):
279 selected = queryset.values_list('id', flat=True)
280 selected = ",".join("%s" % val for val in selected)
281 return HttpResponseRedirect(
282 "/admin/confirmation/%s/%s?ids=%s" %
283 ('actualite', 'visible', selected)
284 )
285
286 def rendre_invisible(self, request, queryset):
287 selected = queryset.values_list('id', flat=True)
288 selected = ",".join("%s" % val for val in selected)
289 return HttpResponseRedirect(
290 "/admin/confirmation/%s/%s?ids=%s" %
291 ('actualite', 'invisible', selected)
292 )
293
294 def assigner_regions(self, request, queryset):
295 selected = queryset.values_list('id', flat=True)
296 selected = ",".join("%s" % val for val in selected)
297 return HttpResponseRedirect(url(
298 'assigner_regions',
299 kwargs={'app_name': 'savoirs', 'model_name': 'actualite'}
300 ) + '?ids=' + selected)
301 assigner_regions.short_description = u'Assigner des régions'
302
303 def assigner_disciplines(self, request, queryset):
304 selected = queryset.values_list('id', flat=True)
305 selected = ",".join("%s" % val for val in selected)
306 return HttpResponseRedirect(url(
307 'assigner_disciplines',
308 kwargs={'app_name': 'savoirs', 'model_name': 'actualite'}
309 ) + '?ids=' + selected)
310 assigner_disciplines.short_description = u'Assigner des disciplines'
311
312 admin.site.register(Actualite, ActualiteAdmin)
313
314
315 class ActualiteVoirAdmin(ActualiteAdmin):
316
317 actions = None
318 list_editable = ()
319 fields = (
320 'titre', 'texte', 'url', 'date', 'visible', 'ancienid', 'source',
321 'disciplines', 'regions'
322 )
323
324 def __init__(self, model, admin_site):
325 super(ActualiteVoirAdmin, self).__init__(model, admin_site)
326 self.readonly_fields = self.fields
327
328
329 admin.site.register(ActualiteVoir, ActualiteVoirAdmin)
330
331
332 class SourceActualiteAdmin(admin.ModelAdmin):
333 actions = ('update_sources',)
334 list_display = ('nom', 'url', 'type')
335 list_filter = ('type',)
336
337 def update_sources(self, request, queryset):
338 for source in queryset:
339 source.update()
340 update_sources.short_description = u'Mettre à jour les fils sélectionnés'
341
342 admin.site.register(SourceActualite, SourceActualiteAdmin)
343
344
345 class EvenementAdminForm(forms.ModelForm):
346 mots_cles = forms.CharField(label='Mots-clés', required=False)
347
348 class Meta:
349 model = Evenement
350
351 def clean(self,):
352 cleaned_data = self.cleaned_data
353 debut = cleaned_data.get("debut")
354 fin = cleaned_data.get("fin")
355 if debut and fin and debut > fin:
356 raise forms.ValidationError(
357 "La date de fin ne doit pas être antérieure à la date de début"
358 )
359 return cleaned_data
360
361
362 class EvenementAdmin(admin.ModelAdmin):
363 form = EvenementAdminForm
364 list_filter = (
365 'approuve', AllRegionsListFilter, 'discipline', 'discipline_secondaire'
366 )
367 list_display = ('titre', 'debut', 'fin', 'ville', 'pays', 'approuve')
368 fields = ('titre', 'discipline', 'discipline_secondaire', 'mots_cles',
369 'type', 'adresse', 'ville', 'pays', 'fuseau', 'debut', 'fin',
370 'piece_jointe', 'regions', 'description', 'prenom', 'nom',
371 'courriel', 'url', 'approuve')
372 search_fields = ('titre', 'description')
373 actions = ('assigner_regions', 'assigner_disciplines')
374
375 def queryset(self, request):
376 return Evenement.all_objects.get_query_set()
377
378 def assigner_regions(self, request, queryset):
379 selected = queryset.values_list('id', flat=True)
380 selected = ",".join("%s" % val for val in selected)
381 return HttpResponseRedirect(url(
382 'assigner_regions',
383 kwargs={'app_name': 'savoirs', 'model_name': 'evenement'}
384 ) + '?ids=' + selected)
385 assigner_regions.short_description = u'Assigner des régions'
386
387 def assigner_disciplines(self, request, queryset):
388 selected = queryset.values_list('id', flat=True)
389 selected = ",".join("%s" % val for val in selected)
390 return HttpResponseRedirect(url(
391 'assigner_disciplines',
392 kwargs={'app_name': 'savoirs', 'model_name': 'evenement'}
393 ) + '?ids=' + selected)
394 assigner_disciplines.short_description = u'Assigner des disciplines'
395
396 admin.site.register(Evenement, EvenementAdmin)
397
398
399 class EvenementVoirAdmin(EvenementAdmin):
400
401 actions = None
402 list_editable = ()
403
404 def __init__(self, model, admin_site):
405 super(EvenementVoirAdmin, self).__init__(model, admin_site)
406 self.readonly_fields = self.fields
407
408 admin.site.register(EvenementVoir, EvenementVoirAdmin)
409
410
411 class PageStatiqueAdmin(admin.ModelAdmin):
412 list_display = ('titre', 'id')
413 list_display_links = ('titre', 'id')
414
415 class Media:
416 js = ('js/tiny_mce/tiny_mce.js', 'js/tiny_mce_textareas.js')
417
418 admin.site.register(PageStatique, PageStatiqueAdmin)
419
420
421 admin.site.register(RecordCategorie)