Ajouté des champs à la fiche évènement.
[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
EMS
17
18from models import SourceActualite, Actualite, Discipline, Evenement, Record, ListSet, HarvestLog, Profile
23b5b3d5 19from savoirs.globals import META
6ef8ead4 20
6a6986bc 21class ListSetFilterSpec(RelatedFilterSpec):
22 """
23 Filtre custom automatiquement lié à un field nommé 'listsets'. Il a pour but de s'afficher
24 lorsqu'un server a déjà été présélectionné. Dans ce cas, il affiche une liste qui contient les
25 listsets de ce server.
26 """
27 def __init__(self, f, request, params, model, model_admin):
28 super(ListSetFilterSpec, self).__init__(f, request, params, model, model_admin)
29 self.server_name = request.GET.get('server', None)
30
31 def has_output(self):
32 return self.server_name is not None
33
6a6986bc 34FilterSpec.filter_specs.insert(0, (lambda f: f.name == 'listsets', ListSetFilterSpec))
35
23b5b3d5 36# Ces deux classes permettent d'implémenter la possibilité d'avoir un champs readonly_fields
37# dans l.administration.
38# Ce champs est devenu natif à partir de la version 1.2
39# http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.readonly_fields
40from django import forms
41class ReadOnlyWidget(forms.Widget):
42 def __init__(self, original_value, display_value):
43 self.original_value = original_value
44 self.display_value = display_value
45
46 super(ReadOnlyWidget, self).__init__()
47
48 def render(self, name, value, attrs=None):
49 if self.display_value is not None:
50 output = self.display_value
51 else:
52 output = unicode(self.original_value)
53
d972b61d 54 # pour les relations
55 try:
56 output = ", ".join([ls.name for ls in self.original_value.get_query_set()])
57 except:
58 pass
59
23b5b3d5 60 is_url = re.match('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', output)
61 if is_url:
62 output = "<a target='_blank' href='%s'>%s</a>" % (output, output)
d972b61d 63
23b5b3d5 64 return mark_safe(output)
65
66 def value_from_datadict(self, data, files, name):
67 return self.original_value
68
69class ReadOnlyAdminFields(object):
70 def get_form(self, request, obj=None):
71 form = super(ReadOnlyAdminFields, self).get_form(request, obj)
72
73 if hasattr(self, 'readonly_fields'):
74 for field_name in self.readonly_fields:
75 if field_name in form.base_fields:
76
77 if hasattr(obj, 'get_%s_display' % field_name):
78 display_value = getattr(obj, 'get_%s_display' % field_name)()
79 else:
80 display_value = None
81
82 form.base_fields[field_name].widget = ReadOnlyWidget(getattr(obj, field_name, ''), display_value)
83 form.base_fields[field_name].required = False
84 return form
85
5212238e
EMS
86class RecordAdminQuerySet(QuerySet):
87
88 def filter(self, *args, **kwargs):
89 """Gère des filtres supplémentaires pour l'admin.
90
91 C'est la seule façon que j'ai trouvée de contourner les mécanismes
92 de recherche de l'admin."""
93 search = kwargs.pop('admin_search', None)
94 search_titre = kwargs.pop('admin_search_titre', None)
95 search_sujet = kwargs.pop('admin_search_sujet', None)
96 search_description = kwargs.pop('admin_search_description', None)
97 search_auteur = kwargs.pop('admin_search_auteur', None)
98
99 if search:
100 qs = self
101 search_all = not (search_titre or search_description or search_sujet or search_auteur)
102 fields = []
103 if search_titre or search_all:
104 fields += ['title', 'alt_title']
105 if search_description or search_all:
106 fields += ['description', 'abstract']
107 if search_sujet or search_all:
108 fields += ['subject']
109 if search_auteur or search_all:
110 fields += ['creator', 'contributor']
111
112 for bit in search.split():
113 or_queries = [Q(**{field + '__icontains': bit}) for field in fields]
114 qs = qs.filter(reduce(operator.or_, or_queries))
115
116 if args or kwargs:
117 qs = super(RecordAdminQuerySet, qs).filter(*args, **kwargs)
118 return qs
119 else:
120 return super(RecordAdminQuerySet, self).filter(*args, **kwargs)
23b5b3d5 121
122class RecordAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
a5f76eb4
EMS
123 fields = ['server', 'title', 'creator', 'description', 'modified',
124 'identifier', 'uri', 'source', 'contributor', 'publisher',
125 'type', 'format', 'language', 'disciplines', 'thematiques',
126 'pays', 'regions', 'validated']
23b5b3d5 127
23b5b3d5 128 readonly_fields = []
da9020f3 129
a5f76eb4
EMS
130 list_filter = ('validated', 'server', 'listsets', 'pays', 'regions',
131 'disciplines', 'thematiques')
18dbd2cf
EMS
132 list_display = ('title', 'subject', 'uri_display', 'creator',
133 'est_complet', 'validated',)
134 list_editable = ('validated',)
135 list_per_page = 25
136
137 actions = ['assigner_pays', 'assigner_regions', 'assigner_disciplines',
e3c3296e 138 'assigner_thematiques']
da9020f3 139
23b5b3d5 140 def __init__(self, *args, **kwargs):
141 """Surcharge l'initialisation pour définir les champs de recherche dynamiquement,
142 et les champs en lecture seule uniquement."""
23b5b3d5 143 self.readonly_fields = META.keys()
d972b61d 144 self.readonly_fields.append('listsets')
23b5b3d5 145 super(RecordAdmin, self).__init__(*args, **kwargs)
6d885e0c 146
1719bf4e 147 def queryset(self, request):
5212238e 148 return RecordAdminQuerySet(Record)
77b0fac0
EMS
149
150 # Présentation de l'information
18dbd2cf 151
6d885e0c 152 def est_complet(self, obj):
6d885e0c 153 v = obj.est_complet()
154 return '<img src="/admin_media/img/admin/icon-%s.gif" alt="%d"/>' % (('no','yes')[v], v)
155 est_complet.allow_tags = True
18dbd2cf 156 est_complet.short_description = u'complet'
23b5b3d5 157
18dbd2cf 158 def uri_display(self, obj):
da9020f3 159 return "<a target='_blank' href='%s'>%s</a>" % (obj.uri, obj.uri)
18dbd2cf
EMS
160 uri_display.allow_tags = True
161 uri_display.short_description = u'lien'
da9020f3 162
18dbd2cf 163 def description_display(self, obj):
23b5b3d5 164 max = 140
165 if obj.description is not None and len(obj.description) > max:
166 return "%s..." % obj.description[:max]
167 else:
168 return obj.description
18dbd2cf 169 description_display.short_description = u'description'
da9020f3 170
18dbd2cf 171 # Actions
2be148fe 172
e3c3296e 173 def assigner_pays(self, request, queryset):
174 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
175 return HttpResponseRedirect("/admin/assigner_%s?ids=%s" % ('pays', ",".join(selected)))
18dbd2cf 176 assigner_pays.short_description = u'Assigner des pays'
e3c3296e 177
178 def assigner_regions(self, request, queryset):
179 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
264a3210
EMS
180 return HttpResponseRedirect(url('assigner_regions', kwargs=dict(app_name='savoirs', model_name='record')) + '?ids=' + ','.join(selected))
181 assigner_regions.short_description = u'Assigner des régions'
e3c3296e 182
183 def assigner_thematiques(self, request, queryset):
184 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
185 return HttpResponseRedirect("/admin/assigner_%s?ids=%s" % ('thematiques', ",".join(selected)))
18dbd2cf 186 assigner_thematiques.short_description = u'Assigner des thématiques'
e3c3296e 187
188 def assigner_disciplines(self, request, queryset):
189 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
264a3210
EMS
190 return HttpResponseRedirect(url('assigner_disciplines', kwargs=dict(app_name='savoirs', model_name='record')) + '?ids=' + ','.join(selected))
191 assigner_disciplines.short_description = u'Assigner des disciplines'
116db1fd 192
da9020f3 193admin.site.register(Record, RecordAdmin)
194
d972b61d 195class ListSetAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
9eda5d6c 196 fields = ['spec', 'name', 'server', 'validated' ]
d972b61d 197 list_display = fields
198 readonly_fields = ['spec', 'name', 'server',]
199 list_filter = ('server',)
200
201admin.site.register(ListSet, ListSetAdmin)
202
23b5b3d5 203class HarvestLogAdmin(ReadOnlyAdminFields, admin.ModelAdmin):
a85ba76e 204 fields = ['context', 'name', 'added', 'updated', 'processed', 'record']
23b5b3d5 205 list_display = fields + ['date']
206 admin_order_fields = ['date']
207 search_fields = fields
208 readonly_fields = fields
209 list_filter = ('context',)
210
211admin.site.register(HarvestLog, HarvestLogAdmin)
6d885e0c 212
213class ProfileInline(admin.TabularInline):
214 model = Profile
215 fk_name = 'user'
216 max_num = 1
217
218class UserProfileAdmin(UserAdmin):
219 inlines = [ProfileInline, ]
220
221admin.site.unregister(User)
222admin.site.register(User, UserProfileAdmin)
223
f554ef70 224class ActualiteAdmin(admin.ModelAdmin):
a5f76eb4 225 list_filter = ('visible', 'disciplines', 'regions')
ccbc4363 226 list_display = ('titre', 'source', 'date', 'visible')
011804bb 227 list_editable = ['visible']
264a3210 228 actions = ['rendre_visible', 'rendre_invisible', 'assigner_regions', 'assigner_disciplines']
f554ef70 229
1719bf4e 230 def queryset(self, request):
29e2a8fd 231 return Actualite.all_objects.get_query_set()
1719bf4e 232
f554ef70 233 # actions
234 def rendre_visible(self, request, queryset):
235 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
236 return HttpResponseRedirect("/admin/confirmation/%s/%s?ids=%s" % ('actualite', 'visible', ",".join(selected)))
237
238 def rendre_invisible(self, request, queryset):
239 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
240 return HttpResponseRedirect("/admin/confirmation/%s/%s?ids=%s" % ('actualite', 'invisible', ",".join(selected)))
241
264a3210
EMS
242 def assigner_regions(self, request, queryset):
243 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
244 return HttpResponseRedirect(url('assigner_regions', kwargs=dict(app_name='savoirs', model_name='actualite')) + '?ids=' + ','.join(selected))
245 assigner_regions.short_description = u'Assigner des régions'
246
247 def assigner_disciplines(self, request, queryset):
248 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
249 return HttpResponseRedirect(url('assigner_disciplines', kwargs=dict(app_name='savoirs', model_name='actualite')) + '?ids=' + ','.join(selected))
250 assigner_disciplines.short_description = u'Assigner des disciplines'
251
f554ef70 252admin.site.register(Actualite, ActualiteAdmin)
b7a741ad 253
db2999fa
EMS
254class SourceActualiteAdmin(admin.ModelAdmin):
255 actions = ['update_sources']
011804bb
EMS
256 list_display = ['nom', 'url', 'type']
257 list_filter = ['type']
db2999fa
EMS
258
259 def update_sources(self, request, queryset):
260 for source in queryset:
261 source.update()
262 update_sources.short_description = u'Mettre à jour les fils sélectionnés'
263
264admin.site.register(SourceActualite, SourceActualiteAdmin)
b7a741ad 265
73309469 266class EvenementAdminForm(forms.ModelForm):
86983865 267 mots_cles = forms.CharField(label='Mots-clés', required=False)
86983865 268
73309469 269 class Meta:
270 model = Evenement
271
272 def clean(self,):
273 cleaned_data = self.cleaned_data
274 debut = cleaned_data.get("debut")
275 fin = cleaned_data.get("fin")
7495bc13 276 if debut and fin and debut > fin:
73309469 277 raise forms.ValidationError("La date de fin ne doit pas être antérieure à la date de début")
278 return cleaned_data
279
b7a741ad 280class EvenementAdmin(admin.ModelAdmin):
73309469 281 form = EvenementAdminForm
a5f76eb4 282 list_filter = ('approuve', 'regions', 'discipline', 'discipline_secondaire')
731ef7ab 283 list_display = ('titre', 'debut', 'fin', 'ville', 'pays', 'approuve')
264a3210 284 fields = ['titre', 'discipline', 'discipline_secondaire', 'mots_cles',
731ef7ab
EMS
285 'type', 'adresse', 'ville', 'pays', 'fuseau', 'debut', 'fin', 'piece_jointe', 'regions',
286 'description', 'prenom', 'nom', 'courriel', 'url', 'approuve']
264a3210
EMS
287 actions = ['assigner_regions', 'assigner_disciplines']
288
1719bf4e 289 def queryset(self, request):
29e2a8fd 290 return Evenement.all_objects.get_query_set()
1719bf4e 291
264a3210
EMS
292 def assigner_regions(self, request, queryset):
293 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
294 return HttpResponseRedirect(url('assigner_regions', kwargs=dict(app_name='savoirs', model_name='evenement')) + '?ids=' + ','.join(selected))
295 assigner_regions.short_description = u'Assigner des régions'
296
297 def assigner_disciplines(self, request, queryset):
298 selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
299 return HttpResponseRedirect(url('assigner_disciplines', kwargs=dict(app_name='savoirs', model_name='evenement')) + '?ids=' + ','.join(selected))
300 assigner_disciplines.short_description = u'Assigner des disciplines'
b7a741ad 301
302admin.site.register(Evenement, EvenementAdmin)
303
304
305