动态填充表单集中的字段

发布于 2024-07-24 08:03:01 字数 1836 浏览 2 评论 0原文

我有两个模型,如下所示:

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. 问题,在将表单集发送到模板之前,我运行以下代码:
    i=1
    for form in formset.forms:
        form.fields["sequence"].initial = i
        i += 1

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

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

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

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

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

I have two models that looks like this:

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

...then a modelform that looks like this:

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

    class Meta:
        model = RouteBase

As you can see, the sequence widget is hidden, as I want this field to be automatically handled by django. I want the user to have to just enter the Base via a text box. The sequence is inferred by the order of the textboxes.

I have created a formset with this form for creating/editing all the bases in the route:

RouteBaseFormset = inlineformset_factory(Route, RouteBase, form=RouteBaseForm, extra=5, )

When this formset is created, the sequence field is empty. I need to fill it in with values before I save the formset (else it won't validate). I can think of about 4 ways to go about this

  1. Right before I send the formset off to the template, I run this code:
    i=1
    for form in formset.forms:
        form.fields["sequence"].initial = i
        i += 1

This works fine, except for one problem. When the formset gets submitted back to the view for saving, all 5 extra fields that have been created with the formset are filled in with a sequence value. This causes problems when the user only wants to add 2 or 3 bases to the route. Validation errors popup because the required field "base" is empty for that form. I could run a bit of code after the formset has been POSTed that checks to see if a base is present, if not, remove the sequence, but if I'm going to do that, I may as well...

  1. Run a bit of code when the formset is POSTed that checks to see if a Base has been entered, if so, add a sequence, if not, then leave that field blank. That way when you try to .save() the formset, the empty values ensure that that particular form is not put into the database. The only problem is that I can't do anything to the form until I run .save(commit=False) which I can't do because the formset doesn't validate. But I could...

  2. Add the sequence values by copying the request.POST variable and manually setting the sequence, but that seems awfully hacky.

  3. I could also just remove blank=True from one of my RouteBase fields, but I don't really want to do that.

So what should I do here?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

小姐丶请自重 2024-07-31 08:03:01

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

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

If you never intend to have a user edit the sequence field and plan on always calculating it's value on the back end, you can exclude it from the form, rather than having it hidden.

Then you can use commit=False and handle the calculation of your sequence field as needed.

海螺姑娘 2024-07-31 08:03:01
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"] = ""

老实说,这似乎比任何乱七八糟的表单验证都要有效。 它也不像我想象的那么黑客......

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"] = ""

Honestly, this seems to work better than any messing around with form validation. It's not as hacky as I thought it be either...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文