I need to perform case-insensitive queries on username
by default when using the Django Auth framework.
我需要在使用Django Auth框架时默认对用户名执行不区分大小写的查询。
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-
我尝试通过编写Queryset的自定义子类并覆盖_filter_or_exclude方法然后在User模型的自定义管理器中使用该子类来解决问题 -
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')
.
但是这种方法不起作用,当我尝试使用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.
更新:顺便说一句,我只想提一下,当我将_filter_or_exclude方法中的逻辑复制到实际的QuerySet类中时,它可以完美地工作。
3 个解决方案
#1
4
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.
无法将管理器添加到具有简单属性分配的类(User.objects = MyManager())。查看ModelBase元类(db / models / base.py),看看在继承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.
您应该能够使用User.add_to_class('objects',MyManager())。或者,您可以创建User的代理子类并在那里添加管理器。
#2
5
You don't want to mess with internal features of Django classes. That way lies trouble with every upgrade in the future.
你不想搞乱Django类的内部功能。这种方式将来会遇到每次升级的麻烦。
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
0
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.
以下是auth用例的配方:Django:来自auth用户的用户名不区分大小写的匹配?您可能最好为每个用例使用单独的解决方案。
#1
4
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.
无法将管理器添加到具有简单属性分配的类(User.objects = MyManager())。查看ModelBase元类(db / models / base.py),看看在继承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.
您应该能够使用User.add_to_class('objects',MyManager())。或者,您可以创建User的代理子类并在那里添加管理器。
#2
5
You don't want to mess with internal features of Django classes. That way lies trouble with every upgrade in the future.
你不想搞乱Django类的内部功能。这种方式将来会遇到每次升级的麻烦。
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
0
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.
以下是auth用例的配方:Django:来自auth用户的用户名不区分大小写的匹配?您可能最好为每个用例使用单独的解决方案。