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