从查询集创建 Django 表单

Creating Django Forms from Querysets

我正在开发一个 Django 表单,让您可以订购海关比萨饼。例如,在将表单构建为 "Select Size" 时,我想从一个数据库中提取菜单项的可用尺寸,这样如果菜单发生变化,表单将自动知道可用的尺寸。

现在我对查询集显示时的返回方式有疑问。

我应该如何修改代码使得

queryset=query_list.values_list('size').distinct()

在下拉列表中显示为:小、中

而不是:(小,),(中,)

或者有没有办法直接从 class 中的 SIZE_CHOICES 元组中提取?

谢谢!

Models.py:

class Pizza(MenuItem):
    STYLE_CHOICES = (
        ('Regular', 'Regular'),
        ('Sicilian', 'Sicilian'),
    )

    SIZE_CHOICES = (
        ('Small', 'Small'),
        ('Large', 'Large'),
    )

    style = models.CharField(max_length=16, blank=False, choices=STYLE_CHOICES)
    size = models.CharField(max_length=16, blank=False, choices=SIZE_CHOICES)
    num_toppings = models.IntegerField()
    toppings = models.ManyToManyField(Topping, blank=True)
    is_special = models.BooleanField(default=False)

    def toppings_list(self):
        return "\n".join([p.name for p in self.toppings.all()])

    def __str__(self):
        return f"{self.style} {self.size}"

forms.py

class PizzaForm(forms.Form):
    query_list = Pizza.objects.all()

    style = forms.ModelChoiceField(
        widget=forms.Select,
        queryset=query_list,
        empty_label="Select Size"
        )
    size_choices = forms.ModelChoiceField(
        widget=forms.Select,
        queryset=query_list.values_list('size').distinct(),
        empty_label="Select Size"
        )
    topping_choices = forms.ModelMultipleChoiceField(
        widget=forms.CheckboxSelectMultiple,
        queryset=Topping.objects.all(),
        required=False
        )

这不是 ModelChoiceField [Django-doc], since you do not select a model object, but a value. You thus can use a ChoiceField [Django-doc],并从模型中导入选择:

class PizzaForm(forms.Form):
    style = <b>forms.ChoiceField</b>(
        widget=forms.Select,
        <b>choices=Pizza.STYLE_CHOICES</b>,
        empty_label="Select Size"
    )
    size_choices = <b>forms.ChoiceField</b>(
        widget=forms.Select,
        <b>choices=Pizza.SIZE_CHOICES</b>,
        empty_label="Select Size"
    )
    topping_choices = forms.ModelMultipleChoiceField(
        widget=forms.CheckboxSelectMultiple,
        queryset=Topping.objects.all(),
        required=False
    )

话虽这么说,您可能想查看 ModelForm [Django-doc]。这可以自动构建基于模型的表单,并且进一步删除大量样板代码到save/update一个Pizza数据库中的对象。

任何希望为非 ModelForm 创建选择字段的人,其中选择动态来自查询集但不是模型实例,您可以将可调用项传递给 [=12= 上的 choices 参数]

def _make_choices():
    return [(c, c) for c in queryset.values_list('field', flat=True)]

choice_field = forms.ChoiceField(choices=_make_choices)

Willem 说,ModelForm 是解决这个问题的方法。