【问题标题】:Django handle 2 forms in UpdateView - form_valid doesn't work (says invalid) - Post works?Django 在 UpdateView 中处理 2 个表单 - form_valid 不起作用(说无效) - 发布工作?
【发布时间】:2021-11-15 06:48:26
【问题描述】:

我有一个应用程序,我将inline_formset 放在对象表单的模板中。表单集适用于所有相关对象。 “主要对象”是GrowthPlan,相关对象是Response 对象。

当我单击“保存”时,所有表单集对象 (Response) 都会正确保存而不会出现问题。

但是,主对象 (GrowthPlan) 没有保存。

form_invalid(self): 方法被调用(我在终端中看到我的打印消息),但没有与表单相关的错误。

form_valid(self): 方法永远不会被调用。

如果我在post 方法中保存表单,它会按预期保存。但由于这是UpdateView,我想用form_validform_invalid 处理它;还是这样做的错误方法?

UpdateView 看起来像这样:

class GrowthPlanUpdateView(
    LoginRequiredMixin, UserIsObserverOrObserveeMixin, UpdateView
):

    model = GrowthPlan
    template_name = "commonground/growthplan_form.html"
    form_class = GrowthPlanForm
    pk_url_kwarg = "growthplan_id"

    def get_object(self):
        return get_object_or_404(GrowthPlan, pk=self.kwargs["growthplan_id"])

    def post(self, request, *args, **kwargs):
        self.object = get_object_or_404(
            GrowthPlan, pk=self.kwargs["growthplan_id"]
        )
        regular_form = GrowthPlanForm(
            request.POST or None, instance=self.object
        )
        # IF I UNCOMMENT THIS - THE FORM SAVES APPROPRIATELY
        #if regular_form.is_valid():
        #   # The form saves if I put this line here
        #   # But the form does not not get to form_valid 
        #   regular_form.save()
        # Handle saving the related formsets here
        response_formset = ResponseInlineFormset(
            request.POST or None,
            prefix="response_formset",
            instance=self.object,
        )
        if response_formset.is_valid():
            for formset_form in response_formset:
                if formset_form.is_valid():
                    # This works
                    formset_form.save()
        return super().post(request, *args, **kwargs)

    def get_form(self):
        return self.form_class(instance=self.object)

    def form_invalid(self, form):
        print("form is invalid")
        # THERE ARE NO ERRORS SHOWING HERE - BUT I SEE MY PRINT STATEMENT
        print(form.errors)
        return super().form_invalid(form)

    def form_valid(self, form):
        # THIS IS NEVER CALLED
        print("getting to form_valid")
        form.save()
        messages.add_message(
            self.request, messages.SUCCESS, "Changes were saved!"
        )
        return super().form_valid(form)

    def get_success_url(self):
        user_id = self.kwargs["user_id"]
        summative_id = self.kwargs["summative_id"]
        evaluation = Evaluation.objects.get(id=self.kwargs["evaluation_id"])
        growthplan = evaluation.growthplan
        return reverse(
            "commonground:growthplan_detail",
            kwargs={
                "user_id": user_id,
                "summative_id": summative_id,
                "evaluation_id": evaluation.id,
                "growthplan_id": growthplan.id,
            },
        )

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        summative = get_object_or_404(
            Summative, pk=self.kwargs["summative_id"]
        )
        if self.request.user != summative.employee:
            context["user_is_observer"] = True
        if self.request.user == summative.employee:
            context["user_is_observer"] = False
        context["employee"] = summative.employee
        try:
            context[
                "employee_information"
            ] = EmployeePayInformation.objects.get(user=summative.employee)
        except EmployeePayInformation.DoesNotExist:
            context["employee_information"] = None
        except EmployeePayInformation.MultipleObjectsReturned:
            # TODO: Log error
            context["employee_information"] = None
        context["response_formset"] = ResponseInlineFormset(
            prefix="response_formset", instance=self.object
        )
        context["growthplan_is_complete"] = False
        if self.object.is_complete:
            context["growthplan_is_complete"] = True
        return context

我的表单 HTML 如下所示:

    <form method="post" novalidate>
        {% csrf_token %}
        {{ form.as_p }}
        {{ response_formset.management_form }}
        {{ formset.management_form }}
        {% for formset_form in response_formset.forms %} 
            {{ formset_form.as_p }}
        {% endfor %}
        <button type="submit" class="btn btn-primary"><i class="fal fa-clipboard-check"></i> Update Growth Plan</button>
    </form>

forms.py 表单如下所示:

class GrowthPlanForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(GrowthPlanForm, self).__init__(*args, **kwargs)

    class Meta:
        model = GrowthPlan
        fields = "__all__"

        widgets = {
            "updated_by": forms.HiddenInput(),
            "evaluation": forms.HiddenInput(),
            "created_by": forms.HiddenInput(),
            "initial_date": DatePickerInput(attrs={"class": "form-control"}),
            "mid_date": DatePickerInput(attrs={"class": "form-control"}),
            "final_date": DatePickerInput(attrs={"class": "form-control"}),
            "expected_growth": forms.TextInput(
                attrs={"class": "form-control"}
            ),
            "actual_growth": forms.TextInput(attrs={"class": "form-control"}),
        }


class ResponseForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(ResponseForm, self).__init__(*args, **kwargs)
        self.fields["question"].queryset = Question.objects.filter(
            id=self.instance.question.id
        )
        self.fields["question"].empty_label = None

    class Meta:
        model = Response
        fields = "__all__"
        widgets = {
            "user": forms.HiddenInput(),
            "growthplan": forms.HiddenInput(),
            "question": forms.HiddenInput(),
            "comment": forms.Textarea(attrs={"class": "form-control"}),
        }

    def clean(self):
        cleaned_data = super().clean()
        comment = cleaned_data.get("comment")
        growthplan = cleaned_data.get("growthplan")
        if growthplan.is_complete and not comment:
            # The comment is required because it should be complete
            self.add_error(
                "comment",
                """
                You must enter a comment before the Growth Plan can be 
                completed.
                """,
            )


ResponseInlineFormset = inlineformset_factory(
    GrowthPlan,
    Response,
    fields=("question", "comment", "user", "growthplan"),
    can_delete=False,
    extra=0,
    form=ResponseForm,
)

我是否应该在 post 方法中处理此问题而忽略 form_validform_invalid 方法?

我应该使用不同的 CBV 吗?

当表单数据实际有效时,为什么会出现form_invalid()

我摸不着头脑 - 任何见解都值得赞赏!

【问题讨论】:

    标签: django django-forms django-class-based-views formset inline-formset


    【解决方案1】:

    对于它的价值 - 如果我从 GrowthPlanUpdateView 中删除了 get_form 覆盖,它会按预期工作,并且该表单现在按预期标记为有效/无效。

    【讨论】:

      猜你喜欢
      • 2013-06-26
      • 1970-01-01
      • 2021-10-17
      • 2016-04-30
      • 2020-09-14
      • 1970-01-01
      • 2021-07-08
      • 2017-08-18
      • 2014-02-28
      相关资源
      最近更新 更多