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