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