Django form returns is_valid() = False and no errors
Asked Answered
L

5

17

I have simple view in django app, which I want to show only when one of the forms is valid. I have something like:

@login_required
@require_role('admin')
def new_package(request):
    invoicing_data_form = InvoicingDataForm(instance=request.user.account.company.invoicingdata)
    if invoicing_data_form.is_valid():
        # all here
        return HttpResponse('Form valid')
    else:
        logger.info("Form invalid")
        return HttpResponse(json.dumps(invoicing_data_form.errors)

I always get log info message that form is invalid, however, I get nothing in

invoicing_data_form.errors

It is very strange, because I am validating this form in other view using user input data and it works just fine. Any idea?

EDIT: Just for clarification. I am not requesting any data from user in this form. I am using this form to validate some model instance (this form is subclassing from ModelForm).

Leger answered 16/2, 2015 at 22:3 Comment(2)
first of all, you need to check for form post.Riehl
Why? I am not sending any data via POST. I just want to validate form (ModelForm) using model instance.Leger
G
23

That's because you're not "feeding" your form.

Do this:

invoicing_data_form = InvoicingDataForm(instance=invoice, data=request.POST or None)
Gegenschein answered 16/2, 2015 at 22:7 Comment(6)
I've added this, but form is still invalid :(Leger
yes but you should be able to inspect the errors nowAcree
you need to check request.POST, if it's empty replace it with something else. If there is no data, the form is unbound and there won't be any error showing.Acree
Using data=request.POST or None will cause that invoicing_data_form.is_bound will always be False. When I change it, for example to data={} then form is bound, but its not validating (because data dict is empty ;))Leger
well I couldn't know without your edit. Anyway the answer remains the same, fill up data ;)Acree
I ended up with something like: invoicing_data_form = InvoicingDataForm(data=request.user.account.company.invoicingdata.__dict__, instance=request.user.account.company.invoicingdata)Leger
C
12

You have an unbound form. https://docs.djangoproject.com/en/1.7/ref/forms/api/#bound-and-unbound-forms

A Form instance is either bound to a set of data, or unbound.

If it’s bound to a set of data, it’s capable of validating that data and rendering the form as HTML with the data displayed in the HTML.

If it’s unbound, it cannot do validation (because there’s no data to validate!), but it can still render the blank form as HTML.

To bind data to a form, pass the data as a dictionary as the first parameter to your Form class constructor:

invoicing_data_form = InvoicingDataForm(request.POST or None, instance=invoice)
Crinite answered 17/2, 2015 at 4:12 Comment(2)
In this view I want to only validate form, I am not requesting any data from user. Thats why I am providing object instance to the form (which is ModelForm class instance). Are you sure thats I need to provide data? Even if so, when I added this, I am still getting form invalid message, and there is no errors at allLeger
Thankyou thankyou thankyouDeceit
C
2

If you're already giving request.POST to your form using request.POST or None, but it's still invalid without errors, check that there isn't any redirect going on. A redirect loses your POST data and your form will be invalid with no errors because it's unbound.

Crimple answered 7/1, 2016 at 9:36 Comment(1)
This answer helped me find my solution. In my case, I was overriding def __init__(self, request): in the form class to add widget/field attributes, but forgetting to pass the request through the super call super(Form, self).__init__(request). Same idea, I was losing the request object prior to calling is_valid().Goggin
C
1

I got this for AuthenticationForm which needs AuthenticationForm(None, request.POST) see Using AuthenticationForm in Django

Carding answered 25/4, 2019 at 0:31 Comment(0)
R
0

I want to expand on the answer by @yuji-tomita-tomita

I typically use a CBV approach in Django, and how I'm handling forms:

def post(self, request, *args, **kwargs):
    form = self.get_form()
    if form.is_valid():
        # do things

Reading the source code I noticed that self.get_form() using get_form_kwargs(self) to populate the form with request.POST, thus getting bound to data. So if you're overloading it like I did:

def get_form_kwargs(self):
    company = self.get_company()
    return {"company": company}

Make sure to call the super(), and it will finally work:

def get_form_kwargs(self):
    company = self.get_company()
    kwargs = super().get_form_kwargs()
    kwargs.update({"company": company})
    return kwargs
Ritter answered 27/1, 2022 at 12:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.