【问题标题】:Django "Duplicate" ModelFormDjango“复制”模型表单
【发布时间】:2011-04-06 02:23:14
【问题描述】:

我想知道是否有一种在 Django 中创建“重复”模型表单的简单方法 - 即预先填充现有模型实例内容的表单(某些字段除外,例如那些唯一的字段),但保存时会创建一个新实例。

我正在考虑向 ModelForm 提供一个实例,以便像使用“编辑”表单一样预填充数据,然后在保存之前将实例设置为 None,但这给出了一个“'NoneType' 对象没有在表单上调用 .save() 时出现属性 'pk'" 错误。似乎在构建表单时提供实例的行为会在最后产生一些依赖。

我很难找到解决这个问题的方法,但我无法想象“重复”表单太独特了,所以也许我遗漏了一些简单的东西?

任何帮助将不胜感激。

【问题讨论】:

  • 你找到可行的解决方案了吗,OP?
  • 这是一段时间(以及 Django 的几个版本)之前的事情,最终并没有成为我们实现的功能。所以不,我从来没有解决过解决方案。虽然@Pydev's answer当时显然对我不起作用,但在较新版本的 Django 中可能是一个不同的故事。但是,它也存在复制太多的风险,因为您是从一个完全填充的模型实例开始的。再说一次,也许这就是你想要的行为。
  • 如果我今天再试一次,我可能会尝试类似@Manoj's answer 的方法。表单知道它包含的字段,因此从给定实例中获取这些字段并使用它们填充initial 的通用解决方案应该不会太难。也许作为工厂类方法,例如MyForm.as_duplicate(data, instance)?
  • 感谢您的跟进!我最终做了一些与你在这里描述的非常相似的事情。模型上处理重复的类方法和我的 WidgetUpdateView 的子类版本,它使用重复方法在form_valid 中交换新实例。

标签: django duplicates modelform


【解决方案1】:

我认为您需要的是一种为表单中的字段填写初始值的方法。完成此任务的最佳方法是从现有实例创建一个初始值字典(以字段名称为键)并将其提供给表单。

类似这样的:

class AddressForm(forms.ModelForm):
    class Meta:
        model = Address

# Inside view:
address = Address.object.get(**conditions)
initial = dict()
for field in ('state', 'zipcode'): # Assuming these are the fields you want to pre-fill
    initial[field] = getattr(address, field)

form = AddressForm(initial = initial)

【讨论】:

    【解决方案2】:
    class AddressForm(forms.ModelForm):
        class Meta:
            model = Address
    
    # Inside view:
    address = Address.object.get(pk=<your-id>)
    address.pk = None # that's the trick, after form save new object will be created
    form = AddressForm(instance=address)
    

    【讨论】:

    • 这似乎不起作用,因为更改 pk 属性似乎不会更改实际的主键字段(在我的情况下为“id”)。因此,ModelForm 仍然会覆盖现有对象,而不是创建新对象。
    • 我相信您需要在将 pk 设置为 None 之后并在传递到表单之前保存模型。我只是在视图中处理这个,所以在保存表单之前,你想做这个交换 (form.instance.pk = None; form.instance.save())
    猜你喜欢
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-22
    • 2019-04-30
    • 2013-04-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多