Django: Perform case-insensitive lookups by default

不羁岁月 提交于 2020-01-03 09:23:20

问题


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.


回答1:


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.




回答2:


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.




回答3:


Here's a recipe for the auth use case: Django : Case insensitive matching of username from auth user? You're probably best off using separate solutions for each of your use cases.



来源:https://stackoverflow.com/questions/531892/django-perform-case-insensitive-lookups-by-default

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!