I need to perform case-insensitive queries on username
by default
when using the Django Auth framework.
I tried fixing the issue by writing a custom subclass of Queryset
and overriding the _filter_or_exclude
method and then using that
subclass in a custom manager for the User model-
from django.db.models import Manager
from django.db.models.query import QuerySet
from django.contrib.auth.models import UserManager
class MyQuerySet(QuerySet):
def _filter_or_exclude(self, negate, *args, **kwargs):
if 'username' in kwargs:
kwargs['username__iexact'] = kwargs['username']
del kwargs['username']
return super(MyQuerySet, self)._filter_or_exclude(negate, *args, **kwargs)
class MyUserManager(UserManager):
def get_query_set(self):
return MyQuerySet(self.model)
User.objects = MyUserManager()
But this approach didn't work and I am getting an weird error when I
try doing User.objects.get(username='Foo')
.
Any help would be appreciated.
Update: I am including the exact error that I am getting.
/usr/lib/python2.5/site-packages/django/db/models/query.py in get(self, *args, **kwargs)
295 keyword arguments.
296 """
--> 297 clone = self.filter(*args, **kwargs)
298 num = len(clone)
299 if num == 1:
/usr/lib/python2.5/site-packages/django/db/models/query.py in filter(self, *args, **kwargs)
481 set.
482 """
--> 483 return self._filter_or_exclude(False, *args, **kwargs)
484
485 def exclude(self, *args, **kwargs):
/home/ghoseb/src/git/ocricket.git/ocricket/user/models.py in _filter_or_exclude(self, negate, *args, **kwargs)
38 kwargs['username__iexact'] = kwargs['username']
39 del kwargs['username']
---> 40 return super(MyQuerySet, self)._filter_or_exclude(negate, *args, **kwargs)
41
42 class MyUserManager(UserManager):
/usr/lib/python2.5/site-packages/django/db/models/query.py in _filter_or_exclude(self, negate, *args, **kwargs)
499 clone.query.add_q(~Q(*args, **kwargs))
500 else:
--> 501 clone.query.add_q(Q(*args, **kwargs))
502 return clone
503
/usr/lib/python2.5/django/db/models/sql/query.py in add_q(self, q_object, used_aliases)
/usr/lib/python2.5/django/db/models/sql/query.py in add_filter(self, filter_expr, connector, negate, trim, can_reuse, process_extras)
/usr/lib/python2.5/django/db/models/sql/query.py in get_meta(self)
<type 'exceptions.AttributeError'>: 'NoneType' object has no attribute '_meta'
Update: By the way, I just wanted to mention that when I copy the logic inside my _filter_or_exclude
method into the actual QuerySet
class, it works flawlessly.
You don't want to mess with internal features of Django classes. That way lies trouble with every upgrade in the future.
If you want to change the way people authenticate, write a custom authentication backend.
Here are two recipes.
http://www.davidcramer.net/code/224/logging-in-with-email-addresses-in-django.html
http://www.djangosnippets.org/snippets/577/
Both of these us email instead of username. It's not hard to use case-insensitive query instead of an email query.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With