views:

58

answers:

2

I'm writing a simple auth system to login (and logout) users. The username is an email address, which looks up an email field.

I'm using:

user = User.objects.get(email__exact=email)
# if user obj exists
if user:
    # if authenticate
    if authenticate(user, email, password):
        # create session
        request.session['user'] = user
        # redir
        return HttpResponseRedirect('/home/')
    else:
        return HttpResponseRedirect('/home/login/')
# no user obj found? (no email found actually)
else:
    # redir
    return HttpResponseRedirect('/home/')

to find if a user exists, however if a user is not found Django throws an error:

User matching query does not exist.

All I want to do is see if that query matches a result. How do I count rows?

+2  A: 

Use filter() instead of get().

Ignacio Vazquez-Abrams
D'oh! Thanks a bunch!
dotty
I used user = User.objects.filter(email__exact=email)[0] instead to limit the recordset to only one record.
dotty
Indexing the query set like that will throw an exception if the record does not exist.
Ignacio Vazquez-Abrams
+1  A: 

I think this is probably more what you want:

try:
    user = User.objects.get(email__exact=email)
    if authenticate(user, email, password):
        request.session['user'] = user
        return HttpResponseRedirect('/home/')
    else:
        return HttpResponseRedirect('/home/login/')
except User.DoesNotExist: # A user with the e-mail provided was not found
    return HttpResponseRedirect('/home/')

Personally I think that's cleaner than Ignacio's method, but it's a matter of taste really.

Finally, the last part of your question ("How do I count rows?"):

get only ever returns an object, and raises an exception if no objects match the criteria you passed in, or if multiple objects match the criteria. To get the number of objects in a QuerySet, you can just call len on it:

q = User.objects.filter(email = '[email protected]')
print len(q)

Or, call count():

print User.objects.filter(email = '[email protected]').count()

The former method (len) will be quicker if you've already evaluated the QuerySet (since it's just counting the number of items in a list, effectively); the latter (count()) will be faster if you've not evaluated the QuerySet, since Django will perform a SELECT COUNT(*) behind the scenes, and you avoid loading all the data into memory.

As an aside - why are you directing them to /home/ if the e-mail address isn't matched, and to /home/login/ if their credentials fail? I would have thought it makes more sense to redirect them to the same place for those two cases.

Dominic Rodger
forgot the : after except User.DoesNotExist
dotty
@dotty - thanks, I'm always doing that!
Dominic Rodger
Me too, but your solution is the best one. Thank you.
dotty
I moved the lines "if authentic .... else ....Redirect('/home/login/')"outside the try: statement. Seems to have the same effect and makes a little more sense. Is this wise to do?
dotty
@dotty - looks alright to me, and has the advantage of moving the `try` and `except` closer together.
Dominic Rodger