【发布时间】:2021-11-15 06:48:26
【问题描述】:
我有一个应用程序,我将inline_formset 放在对象表单的模板中。表单集适用于所有相关对象。 “主要对象”是GrowthPlan,相关对象是Response 对象。
当我单击“保存”时,所有表单集对象 (Response) 都会正确保存而不会出现问题。
但是,主对象 (GrowthPlan) 没有保存。
form_invalid(self): 方法被调用(我在终端中看到我的打印消息),但没有与表单相关的错误。
form_valid(self): 方法永远不会被调用。
如果我在post 方法中保存表单,它会按预期保存。但由于这是UpdateView,我想用form_valid 和form_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_valid 和 form_invalid 方法?
我应该使用不同的 CBV 吗?
当表单数据实际有效时,为什么会出现form_invalid()?
我摸不着头脑 - 任何见解都值得赞赏!
【问题讨论】:
标签: django django-forms django-class-based-views formset inline-formset