Django 模型表单:如何为 CharField 显示 select?
Django Modelforms: how to show a select for a CharField?
我在 Django 中使用 ModelForms 创建表单。这很好用。但是,数据库中有一个字段是 charfield,但对于特定的表单,我想将用户可以输入的选项限制为特定项目的列表 - 理想情况下显示在 <select>
中。这样做的正确方法是什么?这是我的代码:
form = ModelForm(request.POST or None, instance=Street.objects.get(pk=1))
在我的模型中:
class Street(models.Model):
name = models.CharField(max_length=255)
我试过以下方法:
from django import forms
CHOICES = [('1', 'First'), ('2', 'Second')]
choice_field = forms.ChoiceField(widget=forms.Select, choices=CHOICES)
form.fields["street"].widget = choice_field
出现此错误:
'ChoiceField' object has no attribute 'attrs'
使用 ModelForm
的首选方法是创建自己的 class:
class StreetForm(forms.ModelForm):
class Meta:
model = Street
fields = '__all__'
这将创建一个用于编辑 Street
属性的表单,例如 name
。
如果你想创建一个街道为 select 的表格,你应该定义一个新表格 - 如果 Street
与另一个模型有关系,则另一个 ModelForm
(即由 ForeignKey 定义),否则为普通 Form
。
假设第二种情况你应该定义:
class OtherForm(forms.Form):
street = forms.ModelChoiceField(queryset=Street.objects.all())
要缩小街道,您有两种选择,具体取决于过滤条件。
对于静态过滤(标准在运行时不会改变),您可以通过定义过滤查询集来缩小记录范围:
class OtherForm(forms.Form):
street = forms.ModelChoiceField(
queryset=Street.objects.filter(name__ilike='a%')
)
对于动态过滤,您可以在 __init__
方法中覆盖字段的查询集实例:
class OtherForm(forms.Form):
street = forms.ModelChoiceField(
queryset=Street.objects.all()
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # must be called first
self.fields["street"].queryset = Street.objects.filter(...)
ModelChoiceField
的默认小部件是 Select
小部件。
但是如果您需要为街道名称准备自定义选项,您应该定义一个选项列表(如您的示例所示)并重新定义 StreetForm
的 name
字段:
STREET_NAME_CHOICES = [
('Street name 1', 'Street name 1'),
('Street name 2', 'Street name 2')
]
class StreetForm(forms.ModelForm):
name = forms.ChoiceField(
widget=forms.Select,
choices=STREET_NAME_CHOICES
)
class Meta:
model = Street
fields = '__all__'
如果您想修复此属性错误,您可以将您的选择作为 python 元组传递或设置 TypedChoiceField() 并为其赋予属性强制引用:
from django import forms
CHOICES = (("1", "First"), ("2", "Second"))
choice_field = forms.ChoiceField(widget=forms.Select, choices=CHOICES)
form.fields["street"].widget = choice_field
我在 Django 中使用 ModelForms 创建表单。这很好用。但是,数据库中有一个字段是 charfield,但对于特定的表单,我想将用户可以输入的选项限制为特定项目的列表 - 理想情况下显示在 <select>
中。这样做的正确方法是什么?这是我的代码:
form = ModelForm(request.POST or None, instance=Street.objects.get(pk=1))
在我的模型中:
class Street(models.Model):
name = models.CharField(max_length=255)
我试过以下方法:
from django import forms
CHOICES = [('1', 'First'), ('2', 'Second')]
choice_field = forms.ChoiceField(widget=forms.Select, choices=CHOICES)
form.fields["street"].widget = choice_field
出现此错误:
'ChoiceField' object has no attribute 'attrs'
使用 ModelForm
的首选方法是创建自己的 class:
class StreetForm(forms.ModelForm):
class Meta:
model = Street
fields = '__all__'
这将创建一个用于编辑 Street
属性的表单,例如 name
。
如果你想创建一个街道为 select 的表格,你应该定义一个新表格 - 如果 Street
与另一个模型有关系,则另一个 ModelForm
(即由 ForeignKey 定义),否则为普通 Form
。
假设第二种情况你应该定义:
class OtherForm(forms.Form):
street = forms.ModelChoiceField(queryset=Street.objects.all())
要缩小街道,您有两种选择,具体取决于过滤条件。
对于静态过滤(标准在运行时不会改变),您可以通过定义过滤查询集来缩小记录范围:
class OtherForm(forms.Form):
street = forms.ModelChoiceField(
queryset=Street.objects.filter(name__ilike='a%')
)
对于动态过滤,您可以在 __init__
方法中覆盖字段的查询集实例:
class OtherForm(forms.Form):
street = forms.ModelChoiceField(
queryset=Street.objects.all()
)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs) # must be called first
self.fields["street"].queryset = Street.objects.filter(...)
ModelChoiceField
的默认小部件是 Select
小部件。
但是如果您需要为街道名称准备自定义选项,您应该定义一个选项列表(如您的示例所示)并重新定义 StreetForm
的 name
字段:
STREET_NAME_CHOICES = [
('Street name 1', 'Street name 1'),
('Street name 2', 'Street name 2')
]
class StreetForm(forms.ModelForm):
name = forms.ChoiceField(
widget=forms.Select,
choices=STREET_NAME_CHOICES
)
class Meta:
model = Street
fields = '__all__'
如果您想修复此属性错误,您可以将您的选择作为 python 元组传递或设置 TypedChoiceField() 并为其赋予属性强制引用:
from django import forms
CHOICES = (("1", "First"), ("2", "Second"))
choice_field = forms.ChoiceField(widget=forms.Select, choices=CHOICES)
form.fields["street"].widget = choice_field