如何解决Django:身份验证用户名是否区分大小写?
经过大量的实验和对User
模型的最小影响,终于实现了它。[感谢 的不同想法]
############ username case-insensitivity ############
class iunicode(unicode):
def __init__(self, value):
super(iunicode, self).__init__(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 custom_getattribute(self, name):
val = object.__getattribute__(self, name)
if name == "username":
val = iunicode(val)
return val
def auth_user_save(self, *args, **kwargs): # Ensures lowercase usernames
username = self.username
if username and type(username) in [unicode, str, iunicode]:
self.username = username.lower() # Only lower case allowed
super(User, self).save(*args, **kwargs)
User.__getattribute__ = custom_getattribute
User.save = MethodType(auth_user_save, None, User)
#####################################################
我测试了它,并按预期工作。:D
因此,这是 :
from django.test.testcases import TestCase
def create_user(data='testuser'):
email = '%s@%s.com' % (data, data)
user = G(User, username=data, email=email, is_active=True)
user.set_password(data)
user.save()
return user
class UsernameCaseInsensitiveTests(TestCase):
def test_user_create(self):
testuser = 'testuser'
user = create_user(testuser)
# Lowercase
self.assertEqual(testuser, user.username)
# Uppercase
user.username = testuser.upper()
user.save()
self.assertEqual(testuser, user.username)
def test_username_eq(self):
testuser = 'testuser'
user = create_user(testuser)
self.assertTrue(isinstance(user.username, iunicode))
self.assertEqual(user.username, testuser)
self.assertEqual(user.username, testuser.upper())
self.assertTrue(user.username == testuser.upper())
self.assertTrue(testuser.upper() == user.username)
self.assertTrue(user.username == iunicode(testuser.upper()))
###################### QuerySet #############################
def _filter_or_exclude(self, negate, *args, **kwargs):
if 'username' in kwargs:
kwargs['username__iexact'] = kwargs['username']
del kwargs['username']
if args or kwargs:
assert self.query.can_filter(),\
"Cannot filter a query once a slice has been taken."
from django.db.models import Q
clone = self._clone()
if negate:
clone.query.add_q(~Q(*args, **kwargs))
else:
clone.query.add_q(Q(*args, **kwargs))
return clone
from django.db.models.query import QuerySet
QuerySet._filter_or_exclude = _filter_or_exclude
#############################################################
这将允许User.objects.get(username='yugal')
并User.objects.get(username='YUgal')
产生相同的用户。
解决方法
Django默认情况下将用户名区分大小写,现在为了进行身份验证,我编写了自己的Authentication
Backend
用户名以在身份验证时处理不区分大小写的用户名。
如所示:http :
//blog.shopfiber.com/?p=220
现在,问题是:
我有各种观点和util方法,与之相比username
有些刺痛。
即
request.user.username == username_from_some_other_system_as_str
现在,如果用户名是yugal
:
request.user.username == 'Yugal' # Returns False
现在,它应该返回True
[我想要实现的目标]
为此,我记得C++
几天Operator Overloading
。但是我认为,对于djangoauth
user
来说,这样做并不是一个好主意,因为auth
user
它与紧密相关django
。同样,重载==
将使其对整个类(不只是对username
字段)不区分大小写。
因此,username
即使进行整体比较,我也应该如何处理这种不区分大小写的问题。
注意:
-
get_username
始终无法创建一种返回小写用户名的方法,因为它将需要重构所有代码才能使用它。您可以一次为您的代码执行此操作,但是如果您使用的是第三方django应用程序,则无法执行此操作。 -
我知道这
user.username.lower() = something.lower()
是可能的,但是容易出错,而不是针对多开发人员设置中经常使用的某些东西的写解决方案。 -
我已
SomeModel.objects.filter(username__iexact=username)
尽可能使用过。但这仍然使系统容易受到任何不了解的开发人员的错误的影响。
=====================================
从概念上找出解决方案,但无法使其工作(帮助):
####### 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
################################################################
我假设to_python
用于将从数据库接收的值转换为unicode
python中的值。但是,我想我to_python
没有接到电话。
这也将确保第三方应用程序不区分大小写,并且不需要任何重构。它将修补
User
其核心。我将添加到__init__.py
我的第一个INSTALLED_APP
我究竟做错了什么 ?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。