« switchingWould this work? »

Monday, November 16th, 2009

Case insensitive usernames in Django

Categories: Computers

Django's authenticate() method treats both username and password as case sensitive. Password HAS to be, because an uppercase password will not create the same hash as a lowercase password. That is understandable. But the username case sensitivity I don't get. Here is my solution. It requires an extra query to the DB, so if anyone can do this better without actually hacking Django, please let me know.

        if loginform.is_valid():
            #make usernames caseinsensitive
            try:
                u = User.objects.get(username__iexact=loginform.cleaned_data['username'])
                username = u.username
            except User.DoesNotExist:
                username = loginform.cleaned_data['username']
            user = authenticate(username=username,password=loginform.cleaned_data['password'])

what is happening here is i am querying the user table for a user whose username matches the provided username case insensitively. if there is one, use the actual stored username as the username passed to authenticate(). if there isn't one, just use the provided username, because they will get the same error message saying it doesn't exist.

any better ideas out there?

permalink 5:42pm by Brandon //5 comments 2509 views

5 comments

Comment from: brandon [Visitor] · http://bhphp.com/
this actually takes more steps. user storage allows both usernames bhenry and BHENRY and even bHeNrY... gross... anyway, the users get stored with all lowercase in my forms.py __init__
11/21/09 @ 23:04
Comment from: Daniel [Visitor]
That´s the way how I implements.

In my forms.py...

def clean_username(self):
username = self.cleaned_data['username']

unique = User.objects.filter(username__iexact=username)
if len(unique)>0:
raise ValidationError(u"User with this username already exists.")
01/25/10 @ 09:05
Comment from: Brandon [Member] Email
nice. i think you can just do

if unique:

instead of

if len(unique) > 0:
01/25/10 @ 09:24
Comment from: Ryan [Visitor]
No django-core hacks required. Just call this view from your urlconf. (PS: allowing pre tags in user comments would facilitate code-submission.)

import django.contrib.auth.views as django_views
def icase_login(request):
if request.method == 'POST':
__uname = request.POST.get('username','')
__try: user = User.objects.get(username__iexact = uname)
__except: user = None
__if user and user.username != uname: # need to fix the request
____qdict = request.POST.copy()
____qdict.__setitem__('username', user.username)
__request.POST = qdict # overwrite with the case sensitive name

return django_views.login(request)
01/25/10 @ 13:32
Comment from: Brandon [Member] Email
this still requires an extra hit to the database. i was saying if you hack the core, you could determine what query to run before hitting the database, and either to iexact or exact depending on the preference passed in to the authenticate function. then you'd only need to query the database once.
02/09/10 @ 11:11

Leave a comment


Your email address will not be revealed on this site.

Your URL will be displayed.
(Line breaks become <br />)
(Name, email & website)
(Allow users to contact you through a message form (your email will not be revealed.)

©2010 by Brandon Contact design by brandonh

Credits: blogtool | dedicated hosting | evoTeam

visits: stats