如何将 optgroups 添加到 django ModelMultipleChoiceField?
Posted
技术标签:
【中文标题】如何将 optgroups 添加到 django ModelMultipleChoiceField?【英文标题】:How to add optgroups to a django ModelMultipleChoiceField? 【发布时间】:2011-04-13 19:41:39 【问题描述】:我有一个带有ModelMultipleChoiceField
类别列表的表格。
我想使用Category.group
字段对类别进行分组。
我认为通过在 init 函数中更改字段.choices
会成功
class CategoriesField(forms.ModelMultipleChoiceField):
def __init__(self, queryset, **kwargs):
super(forms.ModelMultipleChoiceField, self).__init__(queryset, **kwargs)
self.queryset = queryset.select_related()
self.to_field_name=None
group = None
list = []
self.choices = []
for category in queryset:
if not group:
group = category.group
if group != category.group:
self.choices.append((group.title, list))
group = category.group
list = [(category.id, category.name)]
else:
list.append((category.id, category.name))
try:
self.choices.append((group.title, list))
except:
pass
但ModelChoiceIterator
仍然会擦除__init__
函数中设置的self.choices
信息。
我怎样才能以正确的方式做到这一点?
【问题讨论】:
【参考方案1】:实际上它就像我刚刚解释的那样工作,但不要忘记那部分:
class ProfilForm(ModelForm):
categories = CategoriesField(queryset=Category.objects.all().order_by('group'), label=_(u'Catégories'))
【讨论】:
【参考方案2】:你的代码对我有用,谢谢!也可以与 models.ManyToManyField 一起使用,这对其他人可能也很有趣:
from django.db import models
class CustomManyToManyField(models.ManyToManyField):
def formfield(self, *args, **kwargs):
kwargs["form_class"] = CategoriesField
return super().formfield(**kwargs)
我遇到了同样的缓存错误,并且还通过将整个选择更新放在迭代器中来修复它:
class CustomModelChoiceIterator(forms.models.ModelChoiceIterator):
def __iter__(self):
group = ""
subgroup = []
for category in self.queryset:
if not group:
group = category.group
if group != category.group:
yield (group.title, subgroup)
group = category.group
subgroup = [(category.id, category.name)]
else:
subgroup.append((category.id, category.name))
yield (group.title, subgroup)
class CategoriesField(forms.ModelMultipleChoiceField):
iterator = CustomModelChoiceIterator
【讨论】:
【参考方案3】:我发现这个问题/答案很有帮助,但对代码进行了很多更改。上面代码的问题是它只生成了一次列表,然后就被缓存了(查询集只使用一次)。我的代码适用于按“个人资料”(又名作者)排序的“文章”对象,但任何人都应该能够修改它以供使用。它每次都使用一个新的查询集,因此无需重新启动即可更新(除非您将 cache_choices=True
传递给 ArticleMultipleChoiceField
然后将其缓存)。
class ArticleChoiceIterator(forms.models.ModelChoiceIterator):
def __iter__(self):
if self.field.empty_label is not None:
yield ("", self.field.empty_label)
if self.field.cache_choices:
if self.field.choice_cache is None:
last_profile = None
self.field.choice_cache = []
for article in self.queryset.all():
if last_profile != article.profile:
last_profile = article.profile
article_list = []
self.field.choice_cache.append((article.profile.name, article_list))
article_list.append(self.choice(article))
for choice in self.field.choice_cache:
yield choice
else:
last_profile = None
article_choices = []
for article in self.queryset.all():
if last_profile != article.profile:
if article_choices:
yield (getattr(last_profile, 'name', ''), article_choices)
last_profile = article.profile
article_choices = []
article_choices.append(self.choice(article))
if article_choices:
yield (getattr(last_profile, 'name', ''), article_choices)
class ArticleMultipleChoiceField(forms.ModelMultipleChoiceField):
# make sure queryset is ordered by profile first!
def __init__(self, queryset, **kwargs):
super(ArticleMultipleChoiceField, self).__init__(queryset, **kwargs)
self.queryset = queryset.select_related('profile')
self._choices = ArticleChoiceIterator(self)
class PackageForm(forms.ModelForm):
articles = ArticleMultipleChoiceField(
queryset=Article.objects.order_by('profile__name', 'title')
)
【讨论】:
以上是关于如何将 optgroups 添加到 django ModelMultipleChoiceField?的主要内容,如果未能解决你的问题,请参考以下文章
如何添加 optgroup do dijit.form.Select 或其他小部件类型
如何使用 JSON 在 select2 中设置 optgroup
将 select2.js 与多个选择 optgroup 和 knockoutJS 一起使用