Django 在 UpdateView 中处理 2 个表单 - form_valid 不起作用(说无效) - Post 有效吗?
Django handle 2 forms in UpdateView - form_valid doesn't work (says invalid) - Post works?
我有一个应用程序,我将 inline_formset
放在对象表单的模板中。表单集适用于所有相关对象。 'main object'是一个GrowthPlan
,相关对象是Response
个对象。
当我单击 'save' 时,所有表单集对象 (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()
?
我摸不着头脑 - 任何见解都将受到赞赏!
对于它的价值 - 如果我从 GrowthPlanUpdateView
中删除 get_form
覆盖,它会按预期工作并且表格现在按预期标记为 valid/invalid。
我有一个应用程序,我将 inline_formset
放在对象表单的模板中。表单集适用于所有相关对象。 'main object'是一个GrowthPlan
,相关对象是Response
个对象。
当我单击 'save' 时,所有表单集对象 (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()
?
我摸不着头脑 - 任何见解都将受到赞赏!
对于它的价值 - 如果我从 GrowthPlanUpdateView
中删除 get_form
覆盖,它会按预期工作并且表格现在按预期标记为 valid/invalid。