我有两个看起来像这样的模型:
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。序列由文本框的顺序推断。
我创建了一个带有此表单的formset,用于创建/编辑路径中的所有基础:
RouteBaseFormset = inlineformset_factory(Route, RouteBase, form=RouteBaseForm, extra=5, )
创建此formset时,序列字段为空。在保存formset之前我需要用值填充它(否则它将不会验证)。我可以想到四种方法来实现这个目标
i=1 for form in formset.forms: form.fields["sequence"].initial = i i += 1
除了一个问题外,这个工作正常。当formset被提交回视图以进行保存时,所有 5使用formset创建的额外字段将填入序列值。当用户只想向路线添加2或3个碱基时,这会导致问题。弹出验证错误,因为该表单的必填字段“base”为空。我在可以运行一些代码后,在表单集已经POST,检查是否存在一个库,如果没有,删除序列,但如果我要这样做,我可能会良好...
在表单集POSTed时运行一些代码,检查是否已输入Base,如果是,则添加序列,如果没有,则将该字段留空。这样,当您尝试.save()
formset时,空值确保不将特定表单放入数据库。唯一的问题是我不能对表单做任何事情,直到我运行.save(commit=False)
这是我无法做到的,因为formset没有验证。但我可以......
通过复制request.POST
变量并手动设置序列来添加序列值,但这看起来非常糟糕。
我也可以从我的blank=True
个字段中删除RouteBase
,但我真的不想这样做。
那我该怎么办?
答案 0 :(得分:5)
如果您从未打算让用户编辑序列字段并计划始终在后端计算它的值,您可以exclude it from the form,而不是隐藏它。
然后你可以使用commit = False并根据需要处理你的序列字段的计算。
答案 1 :(得分:-2)
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 ......