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 _
8 class FilteredSelectMultiple(forms.SelectMultiple):
10 A SelectMultiple with a JavaScript filter interface.
12 Note that the resulting JavaScript assumes that the SelectFilter2.js
13 library and its dependencies have been loaded in the HTML page.
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)
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)
26 def render(self, name, value, attrs=None, choices=()):
27 from django.conf import settings
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/")
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))
40 class TaggableModelForm(forms.ModelForm):
41 tags = forms.MultipleChoiceField(
42 label=_('tags').capitalize(), required=False,
43 widget=FilteredSelectMultiple(_('tags'), is_stacked=False))
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()]
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)
61 # TODO: Shouldn't be needed
65 class TaggableModelAdmin(admin.ModelAdmin):
66 form = TaggableModelForm
68 def get_form(self, request, obj=None):
69 form = super(TaggableModelAdmin, self).get_form(request, obj)
70 form.tag_model = self.tag_model