Django problem with validating forms
I have been trying to figure out how all this validation works, but I am not getting the hang of it. I read the very few examples on djangoproject, but I am missing concepts and how everything is tied together.
If you could please look at my code and rearrange how things should be, as well as a few explanations, that would be awesome!
So I want to do something very simple: have a login from with email ONLY. When a user types their email, i want to check if it's in the database, and if it is, login. if it is not, i want to raise an error 'user already in database' and suggest that this person goes to /register
So what i currently have is:
view.py:
def emailLogin(request, backend, extra_context=None, initial={}):
form = EmailLoginForm(ini开发者_运维技巧tial=initial)
if request.method == 'POST':
form = EmailLoginForm(initial=initial, data=request.POST)
if form.is_valid():
user = form.do_save()
_no_pass_login(request, user) # my custom login
return redirect('/')
else:
print ('not valid')
return render_jinja(request, 'registration/email_login_form.html',
type="register",
form = form
)
forms.py:
class EmailLoginForm(forms.Form):
email = forms.EmailField()
def do_save(self):
try:
u = User.objects.get(email=self.cleaned_data['email'])
except :
raise forms.ValidationError("Already in DB")
return u
So the whole point is that I am missing concepts - where should a validation error be raised, the view or the form? where is it raised to? who catches it? what needs to be imported in each file etc.
This shouldn't be too difficult but i am totally lost now, and i have no examples I can analyze and mod my code to work, so i am here.
Yes, you do seem to be missing some concepts.
This type of form shouldn't have a save at all. And the whole point of the is_valid()
check is to catch the validation errors - so they should be raised by that call. The way to do that is to define clean
methods on the form. In this case, since you're only checking the email
field, you define a clean_email
method. The code should be identical to what you've currently got in do_save
.
Now, is_valid()
will return False. But there are a couple of tweaks needed in your view to actually show the errors. First, bring that else
block back one indent level, so it matches if request.method == 'POST'
. Now, instead of that print
statement, move the first line - form = EmailLoginForm(initial=initial)
in there. Now, when is_valid()
is False, the view will fall straight through to the render_to_response with an already-instantiated form containing the validation errors. Magic!
I think this is what Daniel was talking about, but it can be confusing if you don't know exactly what's going on. Basically, all the form does is validate your data. All the saving is done in the view.
view.py
def emailLogin(request, backend, extra_context=None, initial={}):
form = EmailLoginForm
if request.method == 'POST':
form = form(initial=initial, data=request.POST)
if form.is_valid():
_no_pass_login(request, user) # my custom login
return redirect('/')
else:
print 'Form not valid'
else:
form = form(initial=initial)
return render_jinja(request, 'registration/email_login_form.html',
type="register",
form = form
)
forms.py
class EmailLoginForm(forms.Form):
email = forms.EmailField()
def clean_email(self, *args, **kwargs):
email = self.cleaned_data['email']
if User.objects.filter(email=email).count() > 0:
raise ValidationError('User with email "%s" already exists' % email)
return email
精彩评论