Django Forms - 构建一个表单,显示来自多个不同模型的字段,但按外键排序

Posted

技术标签:

【中文标题】Django Forms - 构建一个表单,显示来自多个不同模型的字段,但按外键排序【英文标题】:Django Forms - Building a form showing fields from several different models but sorted by a foreign key 【发布时间】:2012-04-30 11:38:33 【问题描述】:

我不确定如何解决这个问题 - 我尝试了很多方法,但结果是提交表单后出现“太多值无法解压”错误。

这是正在使用的模型的简单演示:

class Supplier(models.Model):
    name = models.CharField(max_length=100)

class SupplierLocation(models.Model):
    supplier = models.ForeignKey(Supplier)
    location = models.CharField(max_length=100)

class Product(models.Model):
    supplier = models.ForeignKey(Supplier)
    name = models.CharField(max_length=100)
    price = models.DecimalField(decimal_places=2,max_digits=10)

我想要做的是生成一个包含 2 个单选按钮的表单。 SupplierLocation.location 是标签,SupplierLocation.id 是单选按钮的值。同样,Product.name 将是标签,Product.id 将是单选按钮的值。我的想法是我想将它们分组为按 Supplier.id 排序的块,以便 html 看起来像这样:

<div>
    <table>
        <tr class=" Supplier.name  hidden">
            <td> location.name </td>
            <td><input type="radio" name="location_id" value=" location.id " /></td>
        </tr>
    </table>
    <table>
        <tr class=" Supplier.name  hidden">
            <td> product.name </td>
            <td> product.price </td>
            <td><input type="radio" name="product_id" value=" product.id " /></td>
        </tr>
    </table>
</div>

显然,两个表中都会有多行,我很确定我应该能够使用小部件来代替硬编码的输入字段,但是我很困惑如何实现自定义表单。这个想法是,当页面加载时所有字段都被隐藏,当从页面上的链接中选择供应商时,这些字段在 JS 中可见。

我不确定表单应该是什么样子,以及我应该使用模型表单还是标准表单。在我当前的测试中,我有一个如下所示的表单:

forms.py

class ProductLocationForm(forms.Form):
    PRODUCT_CHOICES = [(p.id, p.name) for p in Product.objects.all()]
    LOCATION_CHOICES = [(l.id, l.name) for l in SupplierLocation.objects.all()]
    product = forms.ChoiceField(widget=forms.Radioselect, choices=PRODUCT_CHOICES)
    location = forms.ChoiceField(widget=forms.RadioSelect, choices=LOCATION_CHOICES)

这给了我产品和位置,但缺少供应商分组或任何隔离供应商的方式,因此我可以使用 JS 隐藏/显示它们。

任何帮助都会很棒。

【问题讨论】:

【参考方案1】:

您可以使用ModelChoiceField 而不是手动构造choices。然后,您将拥有该字段的 queryset 属性,并且可以在模板中进行类似的操作:

% regroup form.fields.product.queryset by supplier as grouped_products %
% for gp in grouped_products %
    Supplier:  gp.grouper  
    % for choice in gp.list %
        <input type="radio" name="product" value=" choice.pk " />  choice 
    % endfor %
% endfor %

【讨论】:

感谢@ilvar - 这很有效。我在构建此表单上浪费了大量时间,而且我知道解决方案将非常简单。 我还有一个问题 - 在这个解决方案中,有没有办法用 radioselect 小部件替换输入标签? 不。 Select 小部件将所有 LI 呈现到一个列表中,因此您将在分组时遇到更多问题。 哦,我忘记将input 标记为checked,所以你应该添加% if choice.pk == form.queryset.value % 或类似的东西。 非常感谢@ilvar - 我真的很感谢你的帮助,让检查值工作真的让我很沮丧。

以上是关于Django Forms - 构建一个表单,显示来自多个不同模型的字段,但按外键排序的主要内容,如果未能解决你的问题,请参考以下文章

使 Django forms.DateField 显示使用本地日期格式

在 Django 表单中动态显示和隐藏字段

Django 电话号码表单字段出错

Django表单

Django 表单字段动态显示

在 Django 中,如何在模板中手动构造表单集?