mark required fields in ajaxable forms
[wolnelektury.git] / src / newtagging / admin.py
1 # -*- coding: utf-8 -*-
2 from django.contrib import admin
3 from django import forms
4 from django.utils.safestring import mark_safe
5 from django.utils.translation import ugettext_lazy as _
6
7
8 class FilteredSelectMultiple(forms.SelectMultiple):
9     """
10     A SelectMultiple with a JavaScript filter interface.
11
12     Note that the resulting JavaScript assumes that the SelectFilter2.js
13     library and its dependencies have been loaded in the HTML page.
14     """
15     def _media(self):
16         from django.conf import settings
17         js = ['js/SelectBox.js', 'js/SelectFilter2.js']
18         return forms.Media(js=['%sadmin/%s' % (settings.STATIC_URL, url) for url in js])
19     media = property(_media)
20
21     def __init__(self, verbose_name, is_stacked, attrs=None, choices=()):
22         self.verbose_name = verbose_name
23         self.is_stacked = is_stacked
24         super(FilteredSelectMultiple, self).__init__(attrs, choices)
25
26     def render(self, name, value, attrs=None, choices=()):
27         from django.conf import settings
28         output = [
29             super(FilteredSelectMultiple, self).render(name, value, attrs, choices),
30             u'<script type="text/javascript">addEvent(window, "load", function(e) {',
31             u'SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % (
32                 name, self.verbose_name.replace('"', '\\"'),
33                 int(self.is_stacked), settings.STATIC_URL + "admin/")
34         ]
35         # TODO: "id_" is hard-coded here. This should instead use the correct
36         # API to determine the ID dynamically.
37         return mark_safe(u''.join(output))
38
39
40 class TaggableModelForm(forms.ModelForm):
41     tags = forms.MultipleChoiceField(
42         label=_('tags').capitalize(), required=False,
43         widget=FilteredSelectMultiple(_('tags'), is_stacked=False))
44
45     def __init__(self, *args, **kwargs):
46         if 'instance' in kwargs:
47             if 'initial' not in kwargs:
48                 kwargs['initial'] = {}
49             kwargs['initial']['tags'] = [tag.id for tag in self.tag_model.objects.get_for_object(kwargs['instance'])]
50         super(TaggableModelForm, self).__init__(*args, **kwargs)
51         self.fields['tags'].choices = [(tag.id, tag.name) for tag in self.tag_model.objects.all()]
52
53     def save(self, commit):
54         obj = super(TaggableModelForm, self).save()
55         tag_ids = self.cleaned_data['tags']
56         tags = self.tag_model.objects.filter(pk__in=tag_ids)
57         self.tag_model.objects.update_tags(obj, tags)
58         return obj
59
60     def save_m2m(self):
61         # TODO: Shouldn't be needed
62         pass
63
64
65 class TaggableModelAdmin(admin.ModelAdmin):
66     form = TaggableModelForm
67
68     def get_form(self, request, obj=None):
69         form = super(TaggableModelAdmin, self).get_form(request, obj)
70         form.tag_model = self.tag_model
71         return form