无法在视图中编辑 django 表单empty_form字段



我使用Django的BaseFormset中的empty_forms来动态地将内联表单附加到父级。适用于编辑/创建视图。

然而,现在我需要实现一个DuplicateView。我基本上使用的是CreateView,在get_context_data((中对其进行调整,以使用要复制的对象填充它。类似这样的东西:

def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
self.object = self.model.objects.get(pk=self.kwargs["pk"])
logger.info(f"ProduitDuplicateView.get_context_data - object id/code: {self.object.pk} {self.object.no_prod}")
if self.request.POST:
# code
else:
ctx["form"] = ProduitForm(instance=self.object)
fourprodfrmset = FourProdFormSet(instance=self.object)
casefrmset = CaseFormSet(instance=self.object)

我确实需要将实例设置为self.object,因为我想为要用相关事件数据复制的基本对象填充现有的内联表单。但是,该inlineform包含父对象的外键,默认情况下,该外键设置为父对象的pk值。对于表单实例,我将其设置为none like so:

for f in formset:
try:
f.initial.pop("fk_produit")
f.fields["fk_produit"].initial = None
except KeyError as ex:
logger.info(f"There was no fk_produit in form.initial for this form of the formset")

这对于表单实例来说很好。然而,我也需要对empty_form执行同样的操作-否则,当我将emtpy_form附加到内联表单集时,它就会被设置为基对象的pk。这意味着以这种方式保存新的内联表单会导致错误(类似于"内联表单的id与父表单的id不同"(。

所以我试着这样设置:

for formset in [fourprodfrmset, casefrmset]:
try:
formset.empty_form.fields["fk_produit"].initial = None
except KeyError as ex:
logger.info(f"Couldn't remove fk_produit initial value in formset empty_form")

然而,由于某种原因,它没有任何效果——如果我在方法的末尾调试它,formset的emtpy_form字段"fk_produit">仍然有其基值(例如,基对象的基值(。

所以。。。。。如何修改empty_form字段的值?PReferry in the View,因为那是我处理所有恶作剧的地方。

我想我当然可以按照模板来做,但这需要更多的工作。。。。我真的会更热衷于处理这个问题。有什么想法吗?

因此,问题的关键在于这个问题有点被误导了——要实现复制,有更好的方法。有关详细信息,请参阅django论坛上的这篇文章。

从本质上讲,DuplicateView可以继承CreateView(甚至可能使用相同的模板(。那么关键的一点是:

myformset.management_form.initial["INITIAL_FORMS"] = 0     # otherwise, django saves the loaded ones in-place in the DB instead of creating new fouprods for this one

基本上,django处理INITIAL_FORMS的方式与保存时通过ajax动态添加的任何表单都有所不同。它试图用初始对象更新DB中的对象,同时为新对象创建一些对象。因此,我本质上是用基本对象中的表单填充第一个表单(例如,复制内联表单(,但随后我用这几行告诉django,它们都是新表单。因此,它将它们保存为实际实例,并引用新创建的对象的PK作为

至于狭义的问题(以防有人真的需要这么做(,没有好的django方法。empty_form是一堆访问者&无法直接编辑的属性。如果你真的想这么做,我想你需要重写渲染器的部分内容(这样最终的html就会发生变化(。我不会碰它的。

一个更好的解决方案是在模板中——类似于:

{% if field.auto-id=="id_mymodel-__prefix__-fk_fieldname" %}
<input type="hidden" name="mymodel-__prefix__-fk_fieldname" id="id_mymodel-__prefix__-fk_fieldname">
{% else %}     
# regular code    
{% endif %}

因此,本质上,找到这个foreign_key对应的字段,然后手动编写html标记,省略值=""部分

最新更新