动态填充表单集中的字段

pri*_*stc 3 django django-forms inline-formset

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

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
Run Code Online (Sandbox Code Playgroud)

...然后是一个看起来像这样的模型:

class RouteBaseForm(ModelForm):
    base = forms.ModelChoiceField(queryset=Base.objects.all(), widget=forms.TextInput)
    sequence = forms.IntegerField(widget=forms.HiddenInput)

    class Meta:
        model = RouteBase
Run Code Online (Sandbox Code Playgroud)

如您所见,序列窗口小部件是隐藏的,因为我希望这个字段由django自动处理.我希望用户只需通过文本框输入Base.序列由文本框的顺序推断.

我创建了一个带有此表单的formset,用于创建/编辑路径中的所有基础:

RouteBaseFormset = inlineformset_factory(Route, RouteBase, form=RouteBaseForm, extra=5, )
Run Code Online (Sandbox Code Playgroud)

创建此formset时,序列字段为空.在保存formset之前我需要用值填充它(否则它将不会验证).我可以想到四种方法

  1. 在我将formset发送到模板之前,我运行以下代码:
    i=1
    for form in formset.forms:
        form.fields["sequence"].initial = i
        i += 1

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

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

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

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

那我该怎么办?

Har*_*old 5

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

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