django - 无法在视图中编辑 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,因为我想填充现有的内联表单,以便使用相关数据复制基础对象。但是,该内联表单包含一个指向父对象的外键,默认设置为父对象的 pk 值。对于表单实例,我将其设置为 none,如下所示:
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字段的值?最好在视图中,因为那是我处理所有那些恶作剧的地方。
当然,我想我可以按照模板来做,但这需要更多的工作......我真的更热衷于在视图中处理它。有任何想法吗?
解决方案
事实证明,问题的关键在于这个问题有点被误导了——要实现复制,有更好的方法。有关详细信息,请参阅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 动态添加的任何表单有所不同。它尝试使用初始对象更新数据库中的对象,同时为较新的对象创建一些对象。因此,我实质上是用基础对象中的表单填充第一个表单(例如复制内联表单),但随后我用这些行告诉 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标签,省略value=""部分。
推荐阅读
- ios - 为什么每当玩家向左或向右时它只播放我的左侧动画?
- java - 通过流转换数组数组
- c - 最大消息长度 MPI_Type_vector 和 MPI_Gather
- c# - C# LDAP AD Authentication,使用 Job Title 进行授权
- java - '(' , ')',
或预期逗号,在 android studio 中出现“TEXT”SQLite 数据库错误 - reactjs - 使用 antd 在组件中创建子菜单失败
- node.js - 几个小时后木偶师放慢了速度
- r - 麻烦从 CRAN_package_db() 基于 colnames 子集 data.frame
- python - 删除无效括号
- angular - 使用 Angular cli 6.0.5 安装 fontawesome 会引发错误 E418