我的表单中包含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
仍然会删除self.choices
函数中设置的__init__
信息。
我怎样才能以正确的方式做到这一点?
答案 0 :(得分:1)
您的代码对我有用,谢谢!也可以与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
答案 1 :(得分:0)
实际上它的工作方式就像我刚解释但不要忘记那部分:
class ProfilForm(ModelForm):
categories = CategoriesField(queryset=Category.objects.all().order_by('group'), label=_(u'Catégories'))
答案 2 :(得分:0)
我发现这个问题/答案很有帮助,但很多时候改变了代码。上面代码的问题是它只生成一次列表然后它被缓存(查询集只使用一次)。我的代码是针对“文章”对象,由“个人资料”(又名作者)订购,但任何人都应该能够修改它以供其使用。它每次都使用一个新的查询集,因此无需重新启动即可更新(除非您将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')
)