Reputation: 2458
I am having trouble figuring out how to control field validation for ModelForms.
Here is my Model Form:
class UserForm(ModelForm):
class Meta:
model = User
fields = ('email', 'password')
Here is how I am rendering my form in the template:
<form method="post" action="">
{% csrf_token %}
{{ userform.as_p }}
<input type="submit" value="Submit" />
</form>
Here is my view:
def login_page(request):
if request.method == 'POST':
userform = UserForm(request.POST)
if userform.is_valid():
email = request.POST['email']
password = request.POST['password']
user = authenticate(username=email, password=password)
if user is not None:
login(request, user)
return redirect('/dashboard/')
else:
# How can I give the user feedback about authentication failute here. Right now it just reloads the form without any messages.
return render(request, "login.html", {"userform": userform})
else:
# Because .is_valid() is called, The userform will validate for email addresses and that a password input is present here.
return render(request, "login.html", {"userform": userform})
else:
userform = UserForm()
return render(request, "login.html", {"userform": userform})
From reading the docs, this seems like it should be as simple as passing my form some custom attribute; but since I am working with a ModelForm, I am unsure whether this is achieved in the same way.
Could anyone provide an example or tips on how best to control ModelForm field errors?
Thanks!
Upvotes: 5
Views: 5683
Reputation: 5807
Very easy, you have multiple ways to display the error messages:
First one:
1- Override the clean method inside your form/modelform:
def clean(self):
# To keep the main validation and error messages
super(your_form_name, self).clean()
# Now it's time to add your custom validation
if len(self.cleaned_data['password']) < 10:
self._errors['password']='your password\'s length is too short'
# you may also use the below line to custom your error message, but it doesn't work with me for some reason
raise forms.ValidationError('Your password is too short')
Second One
By using django built in validators.
You can use the validators inside the models with the custom error message you want like this:
RE = re.compile('^[0-9]{10}$')
field_name = models.CharField('Name', default='your_name',validators=[RegexValidator(regex=RE, message="Inapproperiate Name!")],)
where validators can utilize multiple built-in validation rules that you can validate against.
please refer to this django documentation
also you can use validators inside your forms definition, but the error message inside validators will not work as it did with models in case of errors, to custom error message use the below third method.
Third Method:
skill = forms.CharField(
label = 'SSkill',
min_length = 2,
max_length = 12,
# message kwarg is only usable in models, yet,
#it doesn't spawn error here.
#validators=[RegexValidator(regex=NME, message="In-approperiate number!")],
required = True,
#Errors dictionary
error_messages={'required': 'Please enter your skill','min_length':'very short entry','invalid':'Improper format'},
#Similar to default you pass in model
initial = 'Extreme Coder'
)
Where, requied, min_length, max_length, along with others, are all fomr kw arguments, where the invalid will only be selected when validators a couple of lines above didn't match the criteria you selected inside validators.
Fourth Method
In this method, you will override your modelform's definition like this:
def __init__(self, *args, **kwargs):
super(Your_Form, self).__init__(*args, **kwargs)
self.fields['password'].error_messages['required'] = 'I require that you fill out this field'
Fifth Method:
I have seen some nice way to custom errors in one of the stackoverflow posts like this:
class Meta:
model = Customer
exclude = ('user',)
fields = ['birthday','name']
field_args = {
"name" : {
"error_messages" : {
"required" : "Please let us know what to call you!"
"max_length" : "Too short!!!"
}
}
}
May be there are other/better ways of doing things, but those are the most common, at least to me :-)
I hope this post helps.
Upvotes: 3
Reputation: 308769
The Django authentication app has a built in AuthenticationForm
that you use. If you look at the source code, you can see their approach is to check the username and password inside the clean
method. That way, a validation error can be raised if the username and password combination is invalid, and the form will display the error.
You can import the AuthenticationForm
and use it in your login view with the following import:
from django.contrib.auth.forms import Authentication
You may also be able to use the built in login
view as well. This means you can take advantage of the added functionality, such as displaying a message if the user does not have cookies enabled. It also decreases the chance of you creating a security vulnerability.
Upvotes: 1
Reputation: 53971
If you want to return error or warning messages back to the user (even if there are no errors in the validated form) you can either use the messaging framework, or you can insert custom error messsages into the form.
I think the messaging framework is your best bet - I don't think it's a good idea to inject errors into the form. If someone has entered a wrong username and pword, it's not a validation error, so it shouldn't be treated as such. A validation error should only be thrown if the wrong type of data is entered to a field, not the incorrect value.
Upvotes: 1