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=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, 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
28 output = [super(FilteredSelectMultiple, self).render(name, value, attrs, choices)]
29 output.append(u'<script type="text/javascript">addEvent(window, "load", function(e) {')
30 # TODO: "id_" is hard-coded here. This should instead use the correct
31 # API to determine the ID dynamically.
32 output.append(u'SelectFilter.init("id_%s", "%s", %s, "%s"); });</script>\n' % \
33 (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX))
34 return mark_safe(u''.join(output))
37 class TaggableModelForm(forms.ModelForm):
38 tags = forms.MultipleChoiceField(label=_('tags').capitalize(), required=True, widget=FilteredSelectMultiple(_('tags'), False))
40 def __init__(self, *args, **kwargs):
41 self.tags.choices = [(tag.id, tag.name) for tag in self.tag_model.objects.all()]
42 if 'instance' in kwargs:
43 if 'initial' not in kwargs:
44 kwargs['initial'] = {}
45 kwargs['initial']['tags'] = [tag.id for tag in self.tag_model.objects.get_for_object(kwargs['instance'])]
46 super(TaggableModelForm, self).__init__(*args, **kwargs)
48 def save(self, commit):
49 obj = super(TaggableModelForm, self).save()
50 tag_ids = self.cleaned_data['tags']
51 tags = self.tag_model.objects.filter(pk__in=tag_ids)
52 self.tag_model.objects.update_tags(obj, tags)
56 # TODO: Shouldn't be needed
60 class TaggableModelAdmin(admin.ModelAdmin):
61 form = TaggableModelForm
63 def get_form(self, request, obj=None):
64 form = super(TaggableModelAdmin, self).get_form(request, obj)
65 form.tag_model = self.tag_model