ModelForm 中我的字段之一(django.forms.models.ModelChoiceIterator)的选择变量包含 3 项。 在某些情况下,我只想使用其中一个(“列表”中的第一个)作为实际的 HTML。
这是 Django Python 代码的一部分:
类 MyForm(ModelForm):
def __init__(self, *args, user=None, **kwargs):
choices = self.fields['xxx'].choices
qs = choices.queryset
qs = qs[:1]
...
...
self.fields['xxx'] = forms.ChoiceField(
label="xxx",
widget=forms.Select(
attrs={
'class': 'form-select' }
),
self.fields['xxx'].choices = choices
self.fields['xxx'].choices.queryset = qs
class Meta:
...
model = MyModel
fields = ('xxx')
...
这会引发错误:“列表”对象没有属性“查询集””,并且显然,选择的大小和内容不会改变。
choices 是 django.forms.models.ModelChoiceIterator 的实例
如何减少将在 HTML 中显示的 choices 中的项目数量?
这要看情况。如果您想限制字段的选择并在验证期间应用此限制,您可以尝试如下操作:
from django.forms import ModelForm
class MyForm(ModelForm):
def __init__(self, *kargs, **kwargs):
super().__init__(*kargs, **kwargs)
self.fields["xxx"].queryset = self.fields["xxx"].queryset.filter(
pk=self.fields["xxx"].queryset.first().pk
)
在这种情况下不能使用切片查询集,因为稍后在验证期间无法过滤切片查询集。
另一方面,如果您想限制字段的选择而不影响验证,您可以将字段的迭代器设置为
ModelChoiceIterator
的自定义子类,然后自己在 MyForm
中实例化该字段。
from django.forms import ModelForm
from django.forms.models import ModelChoiceField, ModelChoiceIterator
class FirstItemModelChoiceIterator(ModelChoiceIterator):
def __init__(self, field):
self.field = field
self.queryset = field.queryset[:1]
class FirstItemModelChoiceField(ModelChoiceField):
iterator = FirstItemModelChoiceIterator
class MyForm(ModelForm):
xxx = FirstItemModelChoiceField(queryset=...)
上面的代码不处理空查询集。
在 Django 4.2.7 上测试。