Django by-default implements username as case sensitive, now for authentication I have written my own Authentication Backend
to handle case insensitive usernames while authentication.
As shown in : http://blog.shopfiber.com/?p=220
Now, the problem is :
I have various views and util methods which compares username
to some stings.
i.e.
request.user.username == username_from_some_other_system_as_str
Now, if username is yugal
then:
request.user.username == 'Yugal' # Returns False
Now, it should return True
[ What I wanted to achieve ]
For that I remember from C++
days, Operator Overloading
.
But I don't think simply doing that for django's auth user
would be a good idea, since auth user
is tightly bound with django
.
Also, overloading ==
will make it case-insensitive for the whole class not just for the username
field.
So, how should I go about this username
case-insensitivity even when compared throughout.
Note:
Creating a
get_username
method that returns lower-case username always is not possible, since it would require all code to be re-factored to use it. You can do it for your code for once, but not possible if you are using 3rd party django apps.I know
user.username.lower() = something.lower()
is possible but is bug prone and not the write solution for something so often used in a multi-developer setup.I have used
SomeModel.objects.filter(username__iexact=username)
, wherever possible. But that still leaves the system vulnerable to a mistake by any of un-aware developer.
======================================
Figured out the solution conceptually, but could not make it work ( Help ) :
####### Custom CharField for username case-insensitivity #######
from django.db.models.fields import CharField
class iUnicode:
def __init__(self, value):
self.value = value
def __eq__(self, other):
if isinstance(other, str) or isinstance(other, unicode):
return self.value.lower() == other.lower()
if isinstance(other, self.__class__):
return other == self.value
def __unicode__(self):
return unicode(self.value)
def __str__(self):
return self.__unicode__()
class UsernameCharField(CharField):
def to_python(self, value): # Its not getting called
unicode_val = super(CharField, self).to_python(value)
return iUnicode(unicode_val)
if User._meta.local_fields[1].name == 'username':
User._meta.local_fields[1] = UsernameCharField(max_length=30)
User._meta.local_fields[1].model = User
################################################################
I assume to_python
is used to convert the value received from database to unicode
in python. But, I guess my to_python
is not getting called.
This will also ensure case-insensitivity in 3rd party apps and would not require any re-factoring. It will patch the
User
at its core. I will be adding this to__init__.py
of my firstINSTALLED_APP
What am I doing wrong ?
user
class for comparing names and refactor all existing code. – Byersuser.username
in smth like this:class S(unicode): def __eq__(self, other): return self.lower() == other.lower()
– Auster