Django内联表单集将始终创建新对象,而不是对其进行更新

问题描述 投票:0回答:1

我有2个型号FirstSecond,其FK从SecondFirst。我为2类创建了一个表单,并为Second创建了一个内联表单集。在模板上,我手动设计了表单,并使用jQuery添加了Second的动态表单。

在UpdateView上,表单已正确填充,但是当我提交表单时,所有Second实例都是使用新ID而不是更新它们重新创建的。我仔细检查了HTML上是否有具有正确ID的name = PREFIX-FORM_COUNT-id,但似乎Django忽略了它。

我正在使用Django 2.2.12和Python 3.6

我在这里做了:

models.py

class First(models.Model):
    name = models.CharField(max_length=100, null=False)

class Second(models.Model):
    first= models.ForeignKey(First, null=False, on_delete=models.CASCADE)
    number= models.FloatField(null=False, default=0)

form.py

class FirstForm(forms.ModelForm):

    class Meta:
        model = First
        fields = "__all__"


class SecondForm(forms.ModelForm):
    class Meta:
        model = Second
        fields = "__all__"


SecondsFormset = inlineformset_factory(First, Second, SecondForm)

view.py

class FirstUpdateView(UpdateView):
    template_name = "first.html"
    model = First
    form_class = FirstForm
    context_object_name = "first_obj"

    def get_success_url(self):
        return reverse(...)

    def forms_valid(self, first, seconds):
        try:
            first.save()
            seconds.save()
            messages.success(self.request, "OK!")

        except DatabaseError as err:
            print(err)
            messages.error(self.request, "Ooops!")
        return HttpResponseRedirect(self.get_success_url())

    def post(self, request, *args, **kwargs):
        first_form = FirstForm(request.POST, instance=self.get_object())
        second_forms = SecondsFormset(request.POST, instance=self.get_object(), prefix="second")
        if first_form .is_valid() and second_forms.is_valid():
            return self.forms_valid(first_form , second_forms)
        ...

。html (仅基本标签)

<form method="post">
    {% csrf_token %}
    <input type="text" id="name" value="{{ first_obj.name }}" name="name" required>
    <input type="hidden" name="second-TOTAL_FORMS" value="0" id="second-TOTAL_FORMS">
    <input type="hidden" name="second-INITIAL_FORMS" value="0" id="second-INITIAL_FORMS">
    <input type="hidden" name="second-MIN_NUM_FORMS" value="0" id="second-MIN_NUM_FORMS">
    <div id="seconds_container">
        {% for s in first_obj.second_set.all %}
            <input type="hidden"  name="second-{{forloop.counter0}}-id" value="{{s.pk}}">
            <input type="hidden"  name="second-{{forloop.counter0}}-first" value="{{first_obj.pk}}">
            <input type="number" min="0" max="10" step="1" value="{{s.number}}" name="second-{{forloop.counter0}}-number" required>
        {% endfor %}
    </div>
    <button class="btn btn-success" type="submit">Update</button>
</form>

我检查了Django如何创建表单,它将仅在其上添加DELETE复选框,但所有其他信息均正确存储在表单集中。当我执行.save()时,它将在db上创建新的Second元素,而不是更改它们。我想念什么?

python django django-forms formset inline-formset
1个回答
0
投票

我解决了!我将TOTAL_FORMSINITIAL_FORMS设置为错误的值。从Django的文档中:

total_form_count返回此表单集中的表单总数。 initial_form_count返回表单集中预先填写的表单数,还用于确定需要多少个表单。您可能永远不需要重写这两种方法,因此请确保在执行此操作之前先了解它们的作用。

所以正确的使用方式是:

在视图中:

  • 使用extra = 0生成FormSets

在HTML中:

  • 使用要发布的行数设置TOTAL_FORMS,并在需要添加/删除行的情况下对其进行动态更改;
  • [INITIAL_FORMS的行数已填满(编辑/删除),请不要更改;
  • 要删除预填充的行,请使用DELETE复选框,而不是删除整个行;
© www.soinside.com 2019 - 2024. All rights reserved.