如何在Django中使用forms.ModelForm创建下拉框?

2024-07-05 14:21:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在尝试在我的表单中添加一个下拉框。我尝试的是:

from django import forms
from .models import Car

class CarForm(forms.ModelForm):
    owner_name = forms.CharField(max_length=100, label='Owner Name', required=True)
    car_type = forms.ChoiceField(choices=Car.CarTypes.choices, label='Car Type', required=True)

    class Meta:
        model = Car
        fields = ('owner_name', 'car_type')

它将car_type字段添加到表单中,但出于某种原因,它不是下拉列表(这是一个可以填充的常规空框)。{}看起来像:

    class CarTypes(models.TextChoices):
        X = 'some_x'
        Y = 'somy_y'
        # ...

原因可能是什么

在我的Car类中,我有:car_type = models.CharField(max_length=24, choices=CarTypes.choices, default=CarTypes.X)。可能是吗?我想CharField会让它变成空盒子。但是将其更改为ChoiceField以:module 'django.db.models' has no attribute 'ChoiceField'结尾。如何解决

我尝试了这个approach,但它使用元组而不是类。从这里的示例中,我看到它们使用两个值元组的元组,如(('a','A'),('b','B')),我使用的是类。这可能是原因吗

在我的html中,我有:

    <form method="post" class="form-group">
      {% csrf_token %}
      {% for field in form %}
        <div class="form-group col-md-12 mb-3">
          <label for="{{ field.label }}">{{ field.label }}</label>
          <input type="text" class="form-control" id="{{ field.label }}" name="{{ field.name }}">
        </div>
      {% endfor %}
      <hr class="mb-4">
      <button type="submit" class="btn btn-secondary btn-lg btn-block">Submit New Car</button>
    </form>

这辆车看起来像:


class Car(models.Model):

    class CarTypes(models.TextChoices):
        X = 'some_x'
        Y = 'somy_y'
        # ...

    owner_name = models.CharField(max_length=100,unique=True)
    car_type = models.CharField(max_length=24, choices=CarTypes.choices, default=CarTypes.X)

    def __str__(self):
        return self.owner_name

Tags: nameformfieldmodelstypeformscarlabel
3条回答

您不需要覆盖模型字段。见Field types-Django Docs

If the model field has choices set, then the form field’s widget will be set to Select, with choices coming from the model field’s choices.

以下代码应该执行您想要的操作:

forms.py

from django import forms
from .models import Car

class CarForm(forms.ModelForm):
    class Meta: 
        model = Car 
        fields = ['owner_name', 'car_type']

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields['owner_name'].widget.attrs.update({"class": "form-control"})
        # or iterate over field to add class for each field
        for field in self.fields:
            self.fields[field].widget.attrs.update({'class':"form-control"})

您可以在__init__方法中添加任何html属性

html:

<form method="post" class="form-group">
  {% csrf_token %}
    <div class="form-group col-md-12 mb-3">
      <label for="{{ form.owner_name.label }}">{{ form.owner_name.label }}</label>
      {{ form.owner_name }}
    </div>

    <div class="form-group col-md-12 mb-3">
        <label for="{{ form.car_type.label }}">{{ form.car_type.label }}</label>
        {{ form.car_type }}
    </div>
  <hr class="mb-4">
  <button type="submit" class="btn btn-secondary btn-lg btn-block">Submit New Car</button>
</form>

或者您可以使用^{}-Django Docs将它们包装在<p>标记中

更新


手动渲染窗体:

<form method="post" class="form-group">
    {% csrf_token %}
    <div class="form-group col-md-12 mb-3">
        <label for="{{ form.owner_name.label }}">{{ form.owner_name.label }}</label>
        <input type="text" class="form-control" id="{{ form.owner_name.auto_id }}" name="{{ form.owner_name.name }}">
    </div>

    <div class="form-group col-md-12 mb-3">
        <label for="{{ form.car_type.label }}">{{ form.car_type.label }}</label>
        <select id="{{ form.car_type.auto_id }}" name="{{ form.car_type.name }}">
        {% for value, label in form.fields.car_type.choices %}
            <option value="{{ value }}"{% if form.car_type.value == value %} selected{% endif %}>{{ label }}</option>
        {% endfor %}
        </select>
    </div>
  <hr class="mb-4">
  <button type="submit" class="btn btn-secondary btn-lg btn-block">Submit New Car</button>
</form>

尝试使用以下方法Choices:-

models.py

choices = [
    ('choice1', 'choice1'),
    ('choice2',"choice2"),
    ('choice3',"choice3")
]

class Car(models.Model):

    owner_name = models.CharField(max_length=100,unique=True)
    car_type = models.CharField(max_length=24, choices=choices, default='choice1')

    def __str__(self):
        return self.owner_name

然后别忘了做migrations

请参阅此->https://docs.djangoproject.com/en/3.0/ref/models/fields/#django.db.models.Field.choices

对于Django3.1,可以通过widgets实现这一点。以下是您可以完成此任务的方法:

from django.forms import ModelForm, Select, TextInput
from .models import Car

class CarForm(ModelForm):
    class Meta:
        model = Car
        fields = ('owner_name', 'car_type')
        widgets = {
            'owner_name': TextInput(),
            'car_type': Select(),
        }

模型应该是这样的:

    class Car(models.Model):
        choices = [('X':'some_x'), ('Y': 'some_y']
        owner_name = models.CharField(max_length=100,unique=True)
        car_type = models.CharField(max_length=24, choices=choices, default='some_y')

        def __str__(self):
            return self.owner_name```

相关问题 更多 >