Optimisation de la requête des ressources valides
[auf_savoirs_en_partage_django.git] / auf_savoirs_en_partage / savoirs / admin.py
... / ...
CommitLineData
1# -*- encoding: utf-8 -*-
2import operator
3
4from auf.django.references import models as ref
5from django import forms
6from django.core.urlresolvers import reverse as url
7from django.contrib import admin
8from django.contrib.auth.admin import UserAdmin
9from django.contrib.auth.models import User
10from django.db.models import Q
11from django.db.models.query import QuerySet
12from django.http import HttpResponseRedirect
13
14from auf_savoirs_en_partage.savoirs.globals import META
15from auf_savoirs_en_partage.savoirs.models import \
16 SourceActualite, Actualite, ActualiteVoir, \
17 Evenement, EvenementVoir, Record, RecordEdit, \
18 RecordCategorie, ListSet, HarvestLog, Profile, PageStatique
19
20
21class 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
37class 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
51class 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
90class 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
189admin.site.register(Record, RecordAdmin)
190
191
192class 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
210admin.site.register(RecordEdit, RecordEditAdmin)
211
212
213class ListSetAdmin(admin.ModelAdmin):
214 fields = ('spec', 'name', 'server', 'validated')
215 list_display = fields
216 readonly_fields = ('spec', 'name', 'server')
217 list_filter = ('server',)
218
219admin.site.register(ListSet, ListSetAdmin)
220
221
222class 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
232admin.site.register(HarvestLog, HarvestLogAdmin)
233
234
235class ProfileInline(admin.TabularInline):
236 model = Profile
237 fk_name = 'user'
238 max_num = 1
239
240
241class UserProfileAdmin(UserAdmin):
242 inlines = (ProfileInline,)
243
244admin.site.unregister(User)
245admin.site.register(User, UserProfileAdmin)
246
247
248class 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
296admin.site.register(Actualite, ActualiteAdmin)
297
298
299class 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
313admin.site.register(ActualiteVoir, ActualiteVoirAdmin)
314
315
316class 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
326admin.site.register(SourceActualite, SourceActualiteAdmin)
327
328
329class 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
346class 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
380admin.site.register(Evenement, EvenementAdmin)
381
382
383class 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
392admin.site.register(EvenementVoir, EvenementVoirAdmin)
393
394
395class 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
402admin.site.register(PageStatique, PageStatiqueAdmin)
403
404
405admin.site.register(RecordCategorie)