Django ModelForm 继承、子类化和传入实例

Tra*_*s D 2 django django-forms

我有一个地址模型:

class Address(models.Model):
  line1 = models.CharField(max_length=100)
  ....
Run Code Online (Sandbox Code Playgroud)

和地址表格:

class AddressForm(forms.ModelForm):
  class Meta:
    model = Address
Run Code Online (Sandbox Code Playgroud)

一些模型将有一个地址字段,因此我不想复制+粘贴 AddressForm 中的所有字段,而是想扩展 AddressForm,以便可以重用它。具体来说,我想避免将所有表单字段复制+粘贴到其他应用程序的表单中,并且只有一个 AddressForm.is_valid() 函数。

例如,订单将有一个地址,所以我的计划是这样做:

class Order:
  address = models.ForeignKey(Address, on_delete=models.CASCADE)

class OrderForm(AddressForm):
  class Meta:
    model = Order
Run Code Online (Sandbox Code Playgroud)

但是,当我从 传递一个实例到 OrderForm 时order/views.py,我传递的是 Order 的实例,并且所有 AddressForm 字段都显示为空白:

form = OrderForm(instance=order)
Run Code Online (Sandbox Code Playgroud)

如何从 order.address 字段初始化 AddressForm 字段?

我曾尝试过这个:

class OrderForm(AddressForm):
    def __init__(self, *args, **kwargs):
        kwargs['instance'] = kwargs['instance'].address
        super(OrderForm, self).__init__(*args, **kwargs)
Run Code Online (Sandbox Code Playgroud)

但这不起作用。

有没有办法做到这一点?或者重用 AddressForm 的更好方法?或者只有当 Order 是 Address 的子类时这才有效?

干杯,

Ala*_*air 5

如果您不想子类化地址,那么您应该在视图中使用两个表单,而不是尝试在订单表单中包含地址字段。

if request.method = "POST":
    address_form = AddressForm(request.POST, instance=order.address)
    order_form = OrderForm(request.POST, instance=order)
    if address_form.is_valid() and order_form.is_valid():
        address = address_form.save()
        order = order_form.save()
Run Code Online (Sandbox Code Playgroud)

您的订单表格应排除 的外键Address

class OrderForm(AddressForm):
    class Meta:
    model = Order
    exclude = ['address']
Run Code Online (Sandbox Code Playgroud)

当您创建新实例时,您应该使用 保存订单commit=False,设置地址,然后保存订单:

if request.method = "POST":
    address_form = AddressForm(request.POST)
    order_form = OrderForm(request.POST)
    if address_form.is_valid() and order_form.is_valid():
        address = address_form.save()
        order = order_form.save(commit=False)
        order.address = address
        order.save()
Run Code Online (Sandbox Code Playgroud)