3

我有两个看起来像这样的模型:

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 种方法来解决这个问题

  1. 在我将表单集发送到模板之前,我运行以下代码:
    我=1
    对于 formset.forms 中的表单:
        form.fields["sequence"].initial = i
        我 += 1

这工作正常,除了一个问题。当表单集被提交回视图进行保存时,使用该表单集创建的所有5 个额外字段都将填充一个序列值。当用户只想向路线添加 2 或 3 个碱基时,这会导致问题。验证错误弹出,因为该表单的必填字段“base”为空。我可以在表单集发布后运行一些代码来检查是否存在碱基,如果不存在,则删除序列,但如果我要这样做,我也可以......

  1. POST 表单集时运行一些代码,检查是否输入了 Base,如果是,则添加一个序列,如果没有,则将该字段留空。这样,当您尝试使用表单集时.save(),空值可确保不会将特定表单放入数据库中。唯一的问题是在我运行之前我不能对表单做任何事情,因为表单.save(commit=False)集没有验证。但我可以...

  2. 通过复制request.POST变量并手动设置序列来添加序列值,但这看起来非常糟糕。

  3. 我也可以blank=True从我的一个RouteBase领域中删除,但我真的不想这样做。

那么我应该在这里做什么?

4

2 回答 2

5

如果您从不打算让用户编辑序列字段并计划始终在后端计算其值,则可以将其从表单中排除,而不是将其隐藏。

然后您可以使用 commit=False 并根据需要处理您的序列字段的计算。

于 2009-06-20T17:52:59.590 回答
-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"] = ""

老实说,这似乎比任何搞砸表单验证都好。它也没有我想象的那么糟糕......

于 2009-06-21T15:10:36.983 回答