Django 在模型表单中传递对象初始值

0 投票
2 回答
2601 浏览
提问于 2025-04-18 05:23

我有一个 Django 的模型表单 MyModelFormA,它是为模型 ModelA 创建的(我在 FormView 中使用这些表单)。

我想通过已经存在的 ModelA 对象来给表单传递初始值,如果有更改的话,就创建一个新的对象。

我一直是这样传递初始值的:

def get_form_kwargs(self):
    kwargs = super(MyFormView, self).get_form_kwargs()
    kwargs.update({'instance': ModelAObject})

但我不太明白的是,当表单像下面这样被验证时:

def form_valid(self, form):
    instance = form.save()

它只是更新了现有的 instance 对象,而不是创建一个新的。

  1. 因为 HTTP 请求是无状态的,怎么知道在之前的请求中传递的 instance 是什么呢?

  2. 我该怎么解决这个问题呢?

我想过做一些类似的事情:

def get_initial(self):
    initial = model_to_dict(MyModelAObject)
    return initial

实际上,MyModelFormA 中只有 MyModelA 字段的一个子集。如果一开始把所有字段都作为字典传递,是否会造成什么问题呢?

有没有更优雅的方法来处理这个呢?

2 个回答

0

你可以试试这个:

def form_valid(self, form):
    if form.has_changed()
        instance = form.save(commit=False)
        instance.pk = None
        #if you have id 
        instance.id = None
        instance.save() #will give you new instance.

可以查看一下这个链接:在Django 1.4中,Form.has_changed()和Form.changed_data这两个未文档化的功能是否按预期工作?,了解一下form.has_changed()是怎么工作的。

1
  1. 当你给ModelForm传一个实例时,它会把这个实例的ID字段作为表单的初始值。所以,如果它在POST请求中收到了一个ID,它就会把这个ID当作一个已经存在的对象来处理,并进行更新。

  2. 你需要单独传递每个字段的初始值(也就是除了ID以外的字段)。最好的方法是只传递你需要的字段作为初始值,这样在ModelForm中会更简单。

def get_initial(self):
  return {
      'a': MyModelAObject.a,
      ....
  }

撰写回答