From looking over the documentation, it seems that the form clean() method is only intended to do lightweight syntax-related validation, such as checking that an email address ends in ".com" or ".edu", or ensuring that the user selects no more than three items from a "pick your top three favorite TV shows" list.
I'm working on an application that allows users to set their password and I want to make sure that their password doesn't contain their login or their real name, and the clean() method doesn't seem like the right place to do this kind of checking, both from a design standpoint and also from the practical limitation that the clean() method doesn't have access to the session data.
Where is the best place to do more heavyweight validation? If I do some custom checking in the view after calling form.is_valid()
, is there a way to get back to the standard form error handling?
I have an idea the code might look like this:
def process_login(request):
"""Display or process the login form."""
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
开发者_高级运维password = form.cleaned_data['password']
if password_is_bad(password, request):
# what now?
There're field-specific validation hooks too: clean_$fieldname
. See details in this section of django docs.
Update: As for passing session info to form, this is easily done via attribute assignment:
form = LoginForm(request.POST)
form.session = request.session
then you can access self.session
in clean_password
method.
I prefer to do all validation in the form. If I'm thinking in terms of object responsibilities, I think of the form as the object that describes the components of the form and how to convert between an HTML form and a valid python object, where "valid" includes application-specific requirements.
If a form needs information that it doesn't normally have access to I pass that information to the form's constructor. Untested code follows:
class MyForm(Form):
def __init__(self, session, *args, **kwargs):
self.session = session
super(MyForm, self).__init__(self, *args, **kwargs)
def clean(self):
# does something with self.session
The advantage of this approach is that your views can frequently be made very generic, often to the point of merely passing an instantiated form object to a custom generic view.
If you really want to validate some parts of the form in the view, then you can raise a ValidationError exception, which would take the user back and display your error message.
from django.forms.util import ValidationError
if len( form.cleaned_data['password'] ) < 5:
raise ValidationError('You have to type at least five characters')
精彩评论