【问题标题】:Django Modelforms: how to show a select for a CharField?Django Modelforms:如何显示 CharField 的选择?
【发布时间】:2021-02-11 17:16:04
【问题描述】:

我在 Django 中使用 ModelForms 来创建我的表单。这很好用。但是,数据库中有一个字段是字符字段,但对于特定表单,我想将用户可以输入的选项限制为特定项目列表 - 理想情况下显示在 <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'

【问题讨论】:

  • 您将Field 实例分配为Widget。尝试定义:1)自定义表单,如第一个答案中所述,或2)尝试用form.fields["street"] = choice_field替换字段。首选方式是 1,您可以在其中将 street 字段重新定义为类属性。编辑:如果您想缩小 Street 模型的数据库记录,请尝试重新定义字段的查询集,即 form.fields["street"].queryset = Street.objects.filter(pk__in=(1, 2))

标签: django django-forms modelform


【解决方案1】:

如果您想修复此属性错误,您可以将您的选择作为 python 元组传递或设置 TypedChoiceField() 并为其提供属性强制引用:https://stackoverflow.com/a/18200849/14127147

from django import forms
CHOICES = (("1", "First"), ("2", "Second"))
choice_field = forms.ChoiceField(widget=forms.Select, choices=CHOICES)
form.fields["street"].widget = choice_field

【讨论】:

    【解决方案2】:

    使用ModelForm 的首选方式是创建自己的类:

    class StreetForm(forms.ModelForm):
        class Meta:
            model = Street
            fields = '__all__'
    

    这将创建一个用于编辑Street 属性的表单,例如name

    如果您想创建一个带有可供选择的街道的表单,并且您应该定义一个新表单 - 如果 Street 与另一个模型相关(即由 ForeignKey 定义),则另一个 ModelForm,或者一个普通的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 小部件。

    但如果您需要为街道名称准备自定义选择,您应该定义一个选择列表(如您的示例中所示)并重新定义StreetFormname 字段:

    
    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__'
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-08-20
      • 2016-08-10
      • 1970-01-01
      • 1970-01-01
      • 2019-06-12
      • 2013-12-08
      • 1970-01-01
      • 2022-12-04
      相关资源
      最近更新 更多