【问题标题】:Add foreign key children to model form in Django将外键子项添加到 Django 中的模型表单
【发布时间】:2011-10-13 15:45:10
【问题描述】:

我有以下 Django 模型:

class Contact(models.Model):
    id #primary key
    #Other contact info

class ContactType(models.Model):
    contacttype_choices=(('Primary', 'Primary'),
                         ('Billing', 'Billing'),
                         ('Business', 'Business'),
                         ('Technology', 'Technology'))
    contact=models.ForeignKey(Contact)
    type=models.CharField(choices=contacttype_choices, max_length=30)
    class Meta:
        unique_together=('contact', 'type')

因此,任何联系人对象最多可以有四种联系人类型,每种类型要么存在,要么不存在。我想为Contact 制作一个模型表单,其中包含联系人类型的多项选择字段。当我使用 Contact 实例构建 Contact 表单时,如何使用现有值填充此联系人类型字段?

编辑:为了澄清,我希望为这四个选项中的每一个创建一个复选框,如果表单是使用模型实例实例化的,那么我希望为每个选项检查复选框存在的相关对象的数量,类似于其余字段自动发生的情况。

【问题讨论】:

  • 这句话你完成了吗? ...“所以任何联系对象都可以有最多联系类型。”
  • 谢谢,我错过了。我现在修好了。
  • 这对您有帮助吗? Django multiple choice field
  • 并非如此。我的问题更多是关于在呈现之前用现有值填充表单。
  • 您的意思是仅使用 Primary、Billing(等)填充多项选择字段选项,还是从特定模型生成表单,其中模型已经存在的类型是预先在多项选择字段中选择?

标签: python django django-forms


【解决方案1】:

我可能会这样构建模型,因此我可以在创建/编辑联系人时选择哪种联系人类型。如果 ContactType 关联为 ManyToMany,我们会自动在 ModelForm 中获取 ModelMultpleChoiceField,我们需要做的就是使用 CheckboxSelectMultiple 小部件来获取您要查找的输出。

当我们将 Contact 的实例传递给 ContactForm 时,Django 将绑定任何预先选择的 ContactType 选项并为我们检查复选框。

将每个 ContactType 的标题设置为唯一与联系人和联系人类型上的 unique_together 相同。

#models.py
class Contact(models.Model):
    #other fields
    contact_types = models.ManyToMany(ContactType)

class ContactType(models.Model):
    title = models.CharField(max_length=20, unique=true)

#forms.py
class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact

    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)
        self.fields['contact_types'].widget = forms.CheckboxSelectMultiple()

【讨论】:

  • 我的问题不在于创建选择(甚至不在于在模型和视图之间复制它们)。我的问题是,当使用模型实例实例化模型表单时,它会使用该实例中的值预先填充表单字段,并且我想在不直接属于模型的附加字段中复制该行为。
  • 我将修改我的答案,因为鉴于模型的当前状态,我认为您无法做您想做的事情。
  • 是的,@waffle 的示例有效,但我不认为具有 Contact 外键的 ContactType 是建模该信息的最佳方式。我的 0.02 美元。
  • 感谢您接受我的回答,我很感激,很高兴为您提供帮助。
【解决方案2】:

你尝试过这样的事情吗?

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)
        self.fields['contacttypes'] = forms.MultipleChoiceField(
            choices = CONTACT_TYPE_CHOICES, 
            label = "contact type",
            widget = CheckBoxSelectMultiple
        )

contact = Contact.objects.get(pk=1) # or whatever
types = ContactType.objects.filter(contact = contact)
form = ContactForm(instance=contact, initial={'contacttypes' : types})

【讨论】:

  • 这很成功,只是我不需要在初始化程序中定义附加字段,而是在第二个查询的末尾添加了.values_list('type', flat=True)。我认为这不会起作用,因为initial 的文档说“如果未提供特定值,它们不会用作备用值”,我误解了它。
  • 出于您上面引用的原因,我建议无论如何都使用 init 中的选项定义字段。虽然这一次在没有明确定义的情况下可能会起作用,但我认为您不应该依赖这种行为。
猜你喜欢
  • 1970-01-01
  • 2022-11-23
  • 2018-07-28
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 2011-06-11
  • 2014-08-06
  • 2016-06-02
相关资源
最近更新 更多