动态填充表单集中的字段
Posted
技术标签:
【中文标题】动态填充表单集中的字段【英文标题】:dynamically populating fields in a formset 【发布时间】:2010-11-04 11:20:57 【问题描述】:我有两个看起来像这样的模型:
class RouteBase(models.Model):
base = models.ForeignKey("Base")
route = models.ForeignKey("Route")
sequence = models.IntegerField()
class Route(models.Model):
bases = models.ManyToManyField("Base", through="RouteBase", blank=True)
description = models.TextField(blank=True)
#and a few other attributes omitted for brevity
...然后是一个看起来像这样的模型:
class RouteBaseForm(ModelForm):
base = forms.ModelChoiceField(queryset=Base.objects.all(), widget=forms.TextInput)
sequence = forms.IntegerField(widget=forms.HiddenInput)
class Meta:
model = RouteBase
如您所见,序列小部件是隐藏的,因为我希望该字段由 django 自动处理。我希望用户只需通过文本框输入 Base 即可。顺序由文本框的顺序推断。
我已经使用此表单创建了一个表单集,用于创建/编辑路线中的所有基础:
RouteBaseFormset = inlineformset_factory(Route, RouteBase, form=RouteBaseForm, extra=5, )
创建此表单集时,序列字段为空。在保存表单集之前,我需要用值填充它(否则它不会验证)。我可以想到大约 4 种方法来解决这个问题
-
就在我将表单集发送到模板之前,我运行了以下代码:
这工作正常,除了一个问题。当表单集被提交回视图进行保存时,所有使用该表单集创建的 5 个额外字段将填充一个序列值。当用户只想向路线添加 2 或 3 个碱基时,这会导致问题。验证错误弹出,因为该表单的必填字段“base”为空。我可以在表单集发布后运行一些代码,检查是否存在碱基,如果不存在,则删除序列,但如果我要这样做,我可能会嗯……
在 POST 表单集时运行一些代码,检查是否输入了 Base,如果是,则添加一个序列,如果没有,则将该字段留空。这样,当您尝试.save()
表单集时,空值确保该特定表单不会放入数据库中。唯一的问题是,在我运行 .save(commit=False)
之前我无法对表单做任何事情,因为表单集没有验证,所以我不能这样做。但我可以...
通过复制request.POST
变量并手动设置序列来添加序列值,但这看起来非常老套。
我也可以从我的RouteBase
字段之一中删除blank=True
,但我真的不想这样做。
那我该怎么办呢?
【问题讨论】:
【参考方案1】:newPOST = request.POST.copy()
i=1
for index in range(0, int(request.POST["routebase_set-TOTAL_FORMS"])-1):
if request.POST["routebase_set-" + str(index) + "-base"]:
newPOST["routebase_set-" + str(index) + "-sequence"] = i
i += 1
else:
newPOST["routebase_set-" + str(index) + "-sequence"] = ""
老实说,这似乎比任何搞砸表单验证都要好。它也没有我想象的那么 hacky...
【讨论】:
-1 这很丑。表单验证方法更简单、更清晰。【参考方案2】:如果您从不打算让用户编辑序列字段并计划始终在后端计算其值,您可以exclude it from the form,而不是隐藏它。
然后您可以使用 commit=False 并根据需要处理您的序列字段的计算。
【讨论】:
这似乎不起作用。我排除哪些字段并不重要,如果没有序列,表单将不会验证,因此不会.save(commit=False)
您需要在模型中为该字段设置 blank=True。由于您负责自己(而不是用户)生成该值,因此您不需要对其进行表单验证。以上是关于动态填充表单集中的字段的主要内容,如果未能解决你的问题,请参考以下文章