1 # -*- encoding: utf-8 -*-
5 from django
.core
.urlresolvers
import reverse
as url
6 from django
.db
import models
7 from django
.db
.models
import Q
8 from django
.db
.models
.query
import QuerySet
9 from django
.contrib
import admin
10 from django
.contrib
.auth
.admin
import UserAdmin
11 from django
.contrib
.auth
.models
import User
12 from django
.contrib
.admin
.filterspecs
import RelatedFilterSpec
, FilterSpec
13 from django
.utils
.safestring
import mark_safe
14 from django
.utils
.translation
import ugettext
as _
15 from django
.utils
.encoding
import smart_unicode
, iri_to_uri
16 from django
.http
import HttpResponseRedirect
18 from models
import SourceActualite
, Actualite
, ActualiteVoir
, Discipline
, \
19 Evenement
, EvenementVoir
, Record
, RecordEdit
, RecordCategorie
, \
20 ListSet
, HarvestLog
, Profile
, PageStatique
22 from savoirs
.globals import META
24 class ListSetFilterSpec(RelatedFilterSpec
):
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.
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)
35 return self
.server_name
is not None
37 FilterSpec
.filter_specs
.insert(0, (lambda f
: f
.name
== 'listsets', ListSetFilterSpec
))
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
43 from django
import forms
44 class ReadOnlyWidget(forms
.Widget
):
45 def __init__(self
, original_value
, display_value
):
46 self
.original_value
= original_value
47 self
.display_value
= display_value
49 super(ReadOnlyWidget
, self
).__init__()
51 def render(self
, name
, value
, attrs
=None):
52 if self
.display_value
is not None:
53 output
= self
.display_value
55 output
= unicode(self
.original_value
)
59 output
= ", ".join([ls
.name
for ls
in self
.original_value
.get_query_set()])
63 is_url
= re
.match('http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', output
)
65 output
= "<a target='_blank' href='%s'>%s</a>" % (output
, output
)
67 return mark_safe(output
)
69 def value_from_datadict(self
, data
, files
, name
):
70 return self
.original_value
72 class ReadOnlyAdminFields(object):
73 def get_form(self
, request
, obj
=None):
74 form
= super(ReadOnlyAdminFields
, self
).get_form(request
, obj
)
76 if hasattr(self
, 'readonly_fields'):
77 for field_name
in self
.readonly_fields
:
78 if field_name
in form
.base_fields
:
80 if hasattr(obj
, 'get_%s_display' % field_name
):
81 display_value
= getattr(obj
, 'get_%s_display' % field_name
)()
85 form
.base_fields
[field_name
].widget
= ReadOnlyWidget(getattr(obj
, field_name
, ''), display_value
)
86 form
.base_fields
[field_name
].required
= False
89 class RecordAdminQuerySet(QuerySet
):
91 def filter(self
, *args
, **kwargs
):
92 """Gère des filtres supplémentaires pour l'admin.
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)
104 search_all
= not (search_titre
or search_description
or search_sujet
or search_auteur
)
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']
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
))
120 qs
= super(RecordAdminQuerySet
, qs
).filter(*args
, **kwargs
)
123 return super(RecordAdminQuerySet
, self
).filter(*args
, **kwargs
)
125 class RecordAdmin(ReadOnlyAdminFields
, admin
.ModelAdmin
):
126 fields
= ['server', 'title', 'creator', 'description', 'modified',
127 'identifier', 'uri', 'source', 'contributor', 'publisher',
128 'type', 'format', 'language', 'categorie', 'disciplines',
129 'thematiques','pays', 'regions', 'validated']
133 list_filter
= ('validated', 'server', 'listsets', 'pays', 'regions',
134 'disciplines', 'thematiques', 'categorie')
135 list_display
= ('title', 'subject', 'uri_display', 'creator',
136 'categorie', 'est_complet', 'validated',)
137 list_editable
= ('validated',)
140 actions
= ['assigner_pays', 'assigner_regions', 'assigner_disciplines',
141 'assigner_thematiques', 'assigner_categorie']
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."""
146 self
.readonly_fields
= META
.keys()
147 self
.readonly_fields
.append('listsets')
148 super(RecordAdmin
, self
).__init__(*args
, **kwargs
)
150 def queryset(self
, request
):
151 return RecordAdminQuerySet(Record
)
153 # Présentation de l'information
155 def est_complet(self
, obj
):
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
159 est_complet
.short_description
= u
'complet'
161 def uri_display(self
, obj
):
162 return "<a target='_blank' href='%s'>%s</a>" % (obj
.uri
, obj
.uri
)
163 uri_display
.allow_tags
= True
164 uri_display
.short_description
= u
'lien'
166 def description_display(self
, obj
):
168 if obj
.description
is not None and len(obj
.description
) > max:
169 return "%s..." % obj
.description
[:max]
171 return obj
.description
172 description_display
.short_description
= u
'description'
176 def assigner_pays(self
, request
, queryset
):
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
))
180 assigner_pays
.short_description
= u
'Assigner des pays'
182 def assigner_regions(self
, request
, queryset
):
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
)
186 assigner_regions
.short_description
= u
'Assigner des régions'
188 def assigner_thematiques(self
, request
, queryset
):
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
))
192 assigner_thematiques
.short_description
= u
'Assigner des thématiques'
194 def assigner_disciplines(self
, request
, queryset
):
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
)
198 assigner_disciplines
.short_description
= u
'Assigner des disciplines'
200 def assigner_categorie(self
, request
, queryset
):
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
))
204 assigner_categorie
.short_description
= u
'Assigner une catégorie'
206 admin
.site
.register(Record
, RecordAdmin
)
208 class RecordEditAdmin(RecordAdmin
):
213 def __init__(self
, model
, admin_site
):
214 super(RecordEditAdmin
, self
).__init__(model
, admin_site
)
216 self
.readonly_fields
= self
.fields
218 def get_actions(self
, request
):
219 actions
= super(RecordEditAdmin
, self
).get_actions(request
)
221 del actions
['assigner_pays']
222 del actions
['assigner_thematiques']
223 del actions
[ 'assigner_categorie']
227 def assigner_disciplines(self
, request
, queryset
):
228 selected
= queryset
.values_list('id', flat
=True)
229 selected
= ",".join("%s" % val
for val
in selected
)
230 return HttpResponseRedirect(url('assigner_disciplines', kwargs
=dict(app_name
='savoirs', model_name
='recordedit')) + '?ids=' + selected
)
231 assigner_disciplines
.short_description
= u
'Assigner des disciplines'
233 def assigner_regions(self
, request
, queryset
):
234 selected
= queryset
.values_list('id', flat
=True)
235 selected
= ",".join("%s" % val
for val
in selected
)
236 return HttpResponseRedirect(url('assigner_regions', kwargs
=dict(app_name
='savoirs', model_name
='recordedit')) + '?ids=' + selected
)
237 assigner_regions
.short_description
= u
'Assigner des régions'
239 admin
.site
.register(RecordEdit
, RecordEditAdmin
)
243 class ListSetAdmin(ReadOnlyAdminFields
, admin
.ModelAdmin
):
244 fields
= ['spec', 'name', 'server', 'validated' ]
245 list_display
= fields
246 readonly_fields
= ['spec', 'name', 'server',]
247 list_filter
= ('server',)
249 admin
.site
.register(ListSet
, ListSetAdmin
)
251 class HarvestLogAdmin(ReadOnlyAdminFields
, admin
.ModelAdmin
):
252 fields
= ['context', 'name', 'added', 'updated', 'processed', 'record']
253 list_display
= fields
+ ['date']
254 admin_order_fields
= ['date']
255 search_fields
= ['context', 'name', 'added', 'updated', 'processed', 'record__title']
256 readonly_fields
= fields
257 list_filter
= ('context',)
259 admin
.site
.register(HarvestLog
, HarvestLogAdmin
)
261 class ProfileInline(admin
.TabularInline
):
266 class UserProfileAdmin(UserAdmin
):
267 inlines
= [ProfileInline
, ]
269 admin
.site
.unregister(User
)
270 admin
.site
.register(User
, UserProfileAdmin
)
272 class ActualiteAdmin(admin
.ModelAdmin
):
273 list_filter
= ('visible', 'disciplines', 'regions')
274 list_display
= ('titre', 'source', 'date', 'visible')
275 list_editable
= ['visible']
276 actions
= ['rendre_visible', 'rendre_invisible', 'assigner_regions', 'assigner_disciplines']
278 def queryset(self
, request
):
279 return Actualite
.all_objects
.get_query_set()
282 def rendre_visible(self
, request
, queryset
):
283 selected
= queryset
.values_list('id', flat
=True)
284 selected
= ",".join("%s" % val
for val
in selected
)
285 return HttpResponseRedirect("/admin/confirmation/%s/%s?ids=%s" % ('actualite', 'visible', selected
))
287 def rendre_invisible(self
, request
, queryset
):
288 selected
= queryset
.values_list('id', flat
=True)
289 selected
= ",".join("%s" % val
for val
in selected
)
290 return HttpResponseRedirect("/admin/confirmation/%s/%s?ids=%s" % ('actualite', 'invisible', selected
))
292 def assigner_regions(self
, request
, queryset
):
293 selected
= queryset
.values_list('id', flat
=True)
294 selected
= ",".join("%s" % val
for val
in selected
)
295 return HttpResponseRedirect(url('assigner_regions', kwargs
=dict(app_name
='savoirs', model_name
='actualite')) + '?ids=' + selected
)
296 assigner_regions
.short_description
= u
'Assigner des régions'
298 def assigner_disciplines(self
, request
, queryset
):
299 selected
= queryset
.values_list('id', flat
=True)
300 selected
= ",".join("%s" % val
for val
in selected
)
301 return HttpResponseRedirect(url('assigner_disciplines', kwargs
=dict(app_name
='savoirs', model_name
='actualite')) + '?ids=' + selected
)
302 assigner_disciplines
.short_description
= u
'Assigner des disciplines'
304 admin
.site
.register(Actualite
, ActualiteAdmin
)
306 class ActualiteVoirAdmin(ActualiteAdmin
):
310 fields
= ['titre', 'texte', 'url', 'date', 'visible', 'ancienid', 'source', 'disciplines', 'regions']
312 def __init__(self
, model
, admin_site
):
313 super(ActualiteVoirAdmin
, self
).__init__(model
, admin_site
)
315 self
.readonly_fields
= self
.fields
318 admin
.site
.register(ActualiteVoir
, ActualiteVoirAdmin
)
320 class SourceActualiteAdmin(admin
.ModelAdmin
):
321 actions
= ['update_sources']
322 list_display
= ['nom', 'url', 'type']
323 list_filter
= ['type']
325 def update_sources(self
, request
, queryset
):
326 for source
in queryset
:
328 update_sources
.short_description
= u
'Mettre à jour les fils sélectionnés'
330 admin
.site
.register(SourceActualite
, SourceActualiteAdmin
)
332 class EvenementAdminForm(forms
.ModelForm
):
333 mots_cles
= forms
.CharField(label
='Mots-clés', required
=False)
339 cleaned_data
= self
.cleaned_data
340 debut
= cleaned_data
.get("debut")
341 fin
= cleaned_data
.get("fin")
342 if debut
and fin
and debut
> fin
:
343 raise forms
.ValidationError("La date de fin ne doit pas être antérieure à la date de début")
346 class EvenementAdmin(admin
.ModelAdmin
):
347 form
= EvenementAdminForm
348 list_filter
= ('approuve', 'regions', 'discipline', 'discipline_secondaire')
349 list_display
= ('titre', 'debut', 'fin', 'ville', 'pays', 'approuve')
350 fields
= ['titre', 'discipline', 'discipline_secondaire', 'mots_cles',
351 'type', 'adresse', 'ville', 'pays', 'fuseau', 'debut', 'fin', 'piece_jointe', 'regions',
352 'description', 'prenom', 'nom', 'courriel', 'url', 'approuve']
353 actions
= ['assigner_regions', 'assigner_disciplines']
355 def queryset(self
, request
):
356 return Evenement
.all_objects
.get_query_set()
358 def assigner_regions(self
, request
, queryset
):
359 selected
= queryset
.values_list('id', flat
=True)
360 selected
= ",".join("%s" % val
for val
in selected
)
361 return HttpResponseRedirect(url('assigner_regions', kwargs
=dict(app_name
='savoirs', model_name
='evenement')) + '?ids=' + selected
)
362 assigner_regions
.short_description
= u
'Assigner des régions'
364 def assigner_disciplines(self
, request
, queryset
):
365 selected
= queryset
.values_list('id', flat
=True)
366 selected
= ",".join("%s" % val
for val
in selected
)
367 return HttpResponseRedirect(url('assigner_disciplines', kwargs
=dict(app_name
='savoirs', model_name
='evenement')) + '?ids=' + selected
)
368 assigner_disciplines
.short_description
= u
'Assigner des disciplines'
370 admin
.site
.register(Evenement
, EvenementAdmin
)
372 class EvenementVoirAdmin(EvenementAdmin
):
377 def __init__(self
, model
, admin_site
):
378 super(EvenementVoirAdmin
, self
).__init__(model
, admin_site
)
380 self
.readonly_fields
= self
.fields
383 admin
.site
.register(EvenementVoir
, EvenementVoirAdmin
)
385 class PageStatiqueAdmin(admin
.ModelAdmin
):
386 list_display
= ['titre', 'id']
387 list_display_links
= ['titre', 'id']
390 js
= ['js/tiny_mce/tiny_mce.js', 'js/tiny_mce_textareas.js']
392 admin
.site
.register(PageStatique
, PageStatiqueAdmin
)
395 admin
.site
.register(RecordCategorie
)