Grouping CheckboxSelectMultiple Options in Django

这一生的挚爱 提交于 2019-11-29 07:44:37

After some struggle, here is what I got.

First, make ModelAdmin call a ModelForm:

class OptionAdmin(admin.ModelAdmin):

   form = forms.OptionForm

Then, in the form, use use a custom widget to render:

category = forms.ModelMultipleChoiceField(queryset=models.Category.objects.all(),widget=AdminCategoryBySupercategory)    

Finally, the widget:

class AdminCategoryBySupercategory(forms.CheckboxSelectMultiple):

     def render(self, name, value, attrs=None, choices=()):
         if value is None: value = []
         has_id = attrs and 'id' in attrs
         final_attrs = self.build_attrs(attrs, name=name)
         output = [u'<ul>']
         # Normalize to strings
         str_values = set([force_unicode(v) for v in value])
         supercategories = models.SuperCategory.objects.all()
         for supercategory in supercategories:
             output.append(u'<li>%s</li>'%(supercategory.name))
             output.append(u'<ul>')
             del self.choices
             self.choices = []
             categories = models.Category.objects.filter(super_category=supercategory)
             for category in categories:
                 self.choices.append((category.id,category.name))
             for i, (option_value, option_label) in enumerate(chain(self.choices, choices)):
                 if has_id:
                     final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
                     label_for = u' for="%s"' % final_attrs['id']
                 else:
                     label_for = ''
                 cb = forms.CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
                 option_value = force_unicode(option_value)
                 rendered_cb = cb.render(name, option_value)
                 option_label = conditional_escape(force_unicode(option_label))
                 output.append(u'<li><label%s>%s %s</label></li>' % (label_for, rendered_cb, option_label))
             output.append(u'</ul>')
             output.append(u'</li>')
         output.append(u'</ul>')
         return mark_safe(u'\n'.join(output))

Not the most elegant solution, but hey, it worked.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!