使用Django表单中的选择框(select)时,有时候需要对选项进行分组,以便用户更方便地选择。本文将详细讲解如何在Django的表单中使用分组选择框。
1.创建分组选择框的选项
首先,需要创建选项和选项组。假设我们有一个产品表单,需要用户输入该产品所属的部门。在此示例中,我们创建两个有关部门的选项组:“技术部门”和“其他部门”。选项组中的每个选项都将属于一个选项组,如下所示:
DEPARTMENT_CHOICES = (
('tech', (
('dev', '开发'),
('ops', '运维'),
)
),
('other', (
('hr', '人力资源'),
('sales', '销售'),
)
),
)
2.在表单中使用分组选择框
在Django表单中使用选择框时,需要使用forms.ChoiceField
或forms.ModelChoiceField
类。对于分组选择框,我们可以使用forms.ChoiceField
与widgets.Select
和widgets.OptGroup
结合使用。下面是一个具有分组选择框的示例表单:
from django import forms
class ProductForm(forms.Form):
department = forms.ChoiceField(choices=DEPARTMENT_CHOICES, widget=forms.Select(attrs={'class': 'form-control'}))
在表单中,我们将DEPARTMENT_CHOICES
作为参数传递给forms.ChoiceField
类。然后,我们在widget参数中使用widgets.Select
来生成选择框,并在该选择框中使用widgets.OptGroup
来生成每个部门的选项组。
3.在模板中渲染分组选择框
最后,在模板中使用表单时,可以使用以下方法来渲染分组选择框:
{% for field in form %}
<label>{{ field.label }}:</label>
{% if field.widget.input_type == 'select' %}
<select name="{{ field.name }}" class="{{ field.widget.attrs.class }}">
{% for group_name, group_choices in field.choices %}
<optgroup label="{{ group_name }}">
{% for choice in group_choices %}
<option value="{{ choice.0 }}">{{ choice.1 }}</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
{% else %}
{{ field }}
{% endif %}
{% endfor %}
在模板中,我们首先使用for循环迭代表单中的每个字段。然后,我们检查字段类型是否为选择框(select
)。如果是,则我们使用内部循环迭代field.choices
,并将每个选项渲染为<option>
标签。对于每个选项,我们还使用optgroup
将其包装在其相应的选项组中。
示例说明
下面是两个有关如何使用分组选择框的示例。
示例1:在Django的管理员中使用
假设我们有一个名为Department
的模型,该模型具有两个属性:name
和slug
。我们希望在Django的管理员中使用分组选择框来选择每个部门的名称。此示例显示了如何在模型中定义选项和选项组:
class Department(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(unique=True)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = "Departments"
ordering = ("name",)
@staticmethod
def get_department_choices():
departments = Department.objects.all()
department_choices = [
("tech", (
("", "--------"),
)),
("other", (
("", "--------"),
)),
]
for department in departments:
if department.slug.startswith("tech"):
department_choices[0][1] += ((department.id, department.name), )
else:
department_choices[1][1] += ((department.id, department.name), )
return department_choices
在这个例子中,我们使用了staticmethod
来创建get_department_choices
方法,该方法返回一个选项组列表。该方法将模型中的部门按照部门名称的起始字母进行分组,并将对应的部门添加到相应的选项组中。
接下来,在模型的表单中使用分组选择框,方法与第2步相同:
from django import forms
from .models import Department
class DepartmentForm(forms.Form):
department = forms.ChoiceField(choices=Department.get_department_choices(), widget=forms.Select(attrs={'class': 'form-control'}))
这个选项列表将可以在Django的管理员中使用。为了演示效果,我们将它保存为forms.py
文件。
最后,在模板中渲染分组选择框,我们可以像第3步中那样使用for循环:
{% for form in adminform.forms %}
{% for fieldset in adminform %}
{% for line in fieldset %}
{% for field in line %}
{% if field %}
{% include "admin/includes/fieldset.html" %}
{% endif %}
{% if field.field.name == 'department' %}
{% include "admin/includes/field_choices.html" %}
{% else %}
{{ field.field }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
{% endfor %}
示例2:在Django的视图中使用
在这个例子中,我们将创建一个使用分组选择框的简单表单。这个表单将要求用户选择一个部门并输入一个产品代码。然后,我们将在视图中处理表单提交:
from django.shortcuts import render
from django import forms
DEPARTMENT_CHOICES = (
("tech", (
("dev", "开发"),
("ops", "运维"),
)),
("other", (
("hr", "人力资源"),
("sales", "销售"),
)),
)
class ProductForm(forms.Form):
department = forms.ChoiceField(choices=DEPARTMENT_CHOICES, widget=forms.Select(attrs={'class': 'form-control'}))
code = forms.CharField(max_length=50, widget=forms.TextInput(attrs={'class': 'form-control'}))
def create_product(request):
if request.method == 'POST':
form = ProductForm(request.POST)
if form.is_valid():
department = form.cleaned_data['department']
code = form.cleaned_data['code']
else:
department = ""
code = ""
else:
department = ""
code = ""
form = ProductForm()
context = {
'form': form,
'department': department,
'code': code
}
return render(request, 'create_product.html', context)
在这个视图中,我们首先检查请求方法是否为POST。如果是,则我们验证表单并将用户选择的部门和产品代码保存到相应的变量中。否则,我们将这些变量赋为空白值,并创建一个新表单,以显示在页面中。
接下来,在模板中渲染分组选择框,我们可以像第3步中那样使用for循环:
<form method="post" class="col s12">
{% csrf_token %}
<div class="row">
<div class="input-field col s6">
{{ form.department.label_tag }}
<select name="{{ form.department.name }}" class="{{ form.department.widget.attrs.class }}">
{% for group_name, group_choices in form.department.choices %}
<optgroup label="{{ group_name }}">
{% for choice in group_choices %}
<option value="{{ choice.0 }}" {% if department == choice.1 %} selected {% endif %}>{{ choice.1 }}</option>
{% endfor %}
</optgroup>
{% endfor %}
</select>
</div>
<div class="input-field col s6">
{{ form.code.label_tag }}
{{ form.code }}
</div>
</div>
<button type="submit" class="btn">Submit</button>
</form>
在模板中,我们首先使用for
循环迭代表单中的每个字段。然后,我们使用optgroup
将选项渲染为分组选择框。对于每个选项,我们将其渲染为<option>
标签。如果用户将一个选项选择,则将该选项的值保留在相应的变量中。最后,在表单中添加一个“提交”按钮。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Django 表单模型选择框如何使用分组 - Python技术站