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.
Managers can’t be added to classes with simple attribute assignment (
User.objects = MyManager()). Look at the ModelBase metaclass (db/models/base.py) to see what all is done for you behind the scenes when you subclass Model.You should be able to make it work with
User.add_to_class('objects', MyManager()). Alternatively, you could make a proxy subclass of User and add the manager there.