Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: How to raise an exception when a user submits an unfinished form?

I've got a relatively standard RegistrationForm that looks like this:

class RegisterForm(forms.Form):
    username = forms.CharField(widget=forms.TextInput(attrs={'placeholder': 'username'}), initial='')
    email = forms.EmailField(widget=forms.TextInput(attrs={'placeholder': 'email'}), initial='')
    password = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'password'}), initial='')
    password_repeat = forms.CharField(widget=forms.PasswordInput(attrs={'placeholder': 'retype password'}), initial='')

How could I create a clean method that returns an error when a user forgets to fill in one or more fields? (ie. "You forgot to fill in the email field")

I've tried the following two options in my clean() method (I'll use the password and password_repeat fields as examples):

password = self.cleaned_data['password']
password_repeat = self.cleaned_data['password_repeat']
# initial values are set to '' for all fields, see above.
if password == '':
    raise forms.ValidationError("You forgot to type in a password.")
elif password_repeat == '':
        raise forms.ValidationError("You forgot to retype your password.")

The first option returns:

KeyError at /homepage/

'password'


try:
    password = self.cleaned_data['password']
    password_repeat = self.cleaned_data['password_repeat']
except KeyError(password):
    raise forms.ValidationError("You forgot to fill in the password field.")

The second option returns:

UnboundLocalError at /homepage/

local variable 'password' referenced before assignment


Bonus points if you can provide a solution that allows for the remaining fields to be checked as well (so that I can return an form bound to the data the user successfully submitted).

like image 712
sgarza62 Avatar asked Nov 21 '12 21:11

sgarza62


People also ask

How do I override a form in Django?

You can override forms for django's built-in admin by setting form attribute of ModelAdmin to your own form class.

How do I handle exceptions in Django?

Django Exception ClassesThe base class for DoesNotExist exceptions. If a query does not return any result, this exception is raised. It raises when the requested field does not exist. This exception is raised by a query if only one object is expected, but multiple objects are returned.

What is CharField in Django?

CharField in Django Forms is a string field, for small- to large-sized strings. It is used for taking text inputs from the user. The default widget for this input is TextInput.

How do you increase errors in Django?

To create such an error, you can raise a ValidationError from the clean() method. For example: from django import forms from django. core.


1 Answers

You can use the required property available for all Field types, which automatically does this type of validation. So your code would look like:

class RegisterForm(forms.Form):
    username = forms.CharField(
        widget = forms.TextInput(attrs = {'placeholder': 'username'}),
        required = True)
    email = forms.EmailField(
        widget = forms.TextInput(attrs = {'placeholder': 'email'}),
        required = True)
    password = forms.CharField(
        widget = forms.PasswordInput(attrs = {'placeholder': 'password'}),
        required = True)
    password_repeat = forms.CharField(
        widget = forms.PasswordInput(attrs = {'placeholder': 'retype password'}),
        required = True)

Note: I think you can leave out those initial = '' parameters as well, as shown above.

I'm actually not sure why you're getting the errors you mentioned in your question, perhaps you could post the relevant code from your views.py? It could be because you need to return cleaned_data at the end of any clean method you implement.

I would also just say that your use of the clean method is not quite right. If you refer to this page of the documentation on form and field validation you see that to validate a single field you use the specific clean_<fieldname> method e.g. clean_password_repeat. Using the clean method is appropriate when validation involves multiple field simultaneously, one example of this you may like to use is checking the inputs for the two password fields match.

class RegisterForm(forms.Form):
    # field definitions (above)

    def clean(self):
        password = self.cleaned_data['password']
        password_repeat = self.cleaned_data['password_repeat']
        if password != password_repeat:
            raise forms.ValidationError(u"Passwords do not match.")
        return cleaned_data

Note: Code is not tested.

I hope this was helpful!

like image 125
Max Spencer Avatar answered Sep 30 '22 05:09

Max Spencer