'Django: How to return an inline formset with errors
I have created a form to sign up a user by having them create a User object and a UserProfile object as follows:
class UserCreationForm(UserCreationForm):
class Meta:
model = User
fields = ("email",)
class UserProfileCreationForm(ModelForm):
class Meta:
model = UserProfile
fields = (
"first_name",
"last_name",
)
RegisteredCustomerProfileCreationInlineFormset = inlineformset_factory(
User,
UserProfile,
form=UserProfileCreationForm,
extra=1,
can_delete=False,
can_order=False,
)
In my view to display the sign up form, I do the following:
class UserSignupView(CreateView):
form_class = UserCreationForm
template_name = "users/signup_form.html"
def get_context_data(self, **kwargs):
"""Adds the inline formset to the context."""
context = super(UserSignupView, self).get_context_data(**kwargs)
if self.request.POST:
context[
"user_profile_inline"
] = UserProfileCreationInlineFormset(
self.request.POST
)
else:
context[
"user_profile_inline"
] = UserProfileCreationInlineFormset()
return context
def form_invalid(self, request, form):
# Note: I added request as an argument because I was getting an error that
# says the method is expecting 2 arguments but got 3.
return render(self.request, self.template_name,
self.get_context_data(
form=form
)
)
def form_valid(self, form):
context = self.get_context_data()
user_profile_inline = context["user_profile_inline"]
if (
form.is_valid()
and user_profile_inline.is_valid()
):
# Handle valid case
...
return redirect(
self.request.GET.get(reverse_lazy("index"))
)
else:
self.form_invalid(self, form)
My template is as simple as
<form method="post">
{% csrf_token %}
{{ form.as_p }}
{{ user_profile_inline.as_p }}
<button type="submit" value="Save">Sign Up</button>
</form>
When my form
which is for creation of the User object is invalid, the template is reloaded nicely with the errors in the form. However, when the formset is invalid, I get the error: "didn't return an HttpResponse object. It returned None instead."
Please may you assist me with the correct way of reloading the template with errors for the inline formset.
Solution 1:[1]
For me I had a Function Based View.
If your code looks something like this:
views.py
def fbv(request, model_slug):
modelName = ModelName.objects.get(slug=model_slug)
ModelName2Formset = inlineformset_factory(
ModelName, ModelName2, fields=('field1', 'field2',),
extra=3,
can_delete = True,
widgets={
'field1': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Text here'}),
'field2': forms.NumberInput(attrs={'class': 'form-control', 'placeholder': 'Numbers here'}),
},
)
if request.method == "POST":
formset = ModelName2Formset(request.POST, instance=modelName)
if formset.is_valid():
formset.save()
return HttpResponseRedirect('url-name')
formset = ModelName2Formset(instance=modelName)
return render(request, 'AppName/add-modelName2.html', {'formset' : formset, 'modelName': modelName})
What I did was to add an else to the if request.method == "POST":
views.py
def fbv(request, model_slug):
...
if request.method == "POST":
formset = ModelName2Formset(request.POST, instance=modelName)
if formset.is_valid():
formset.save()
return HttpResponseRedirect('url-name')
# I added else here
else:
formset = ModelName2Formset(instance=modelName)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | AnonymousUser |