Django:用户名和密码用户名不区分大小写匹配 [英] Django : Case insensitive matching of username from auth user?
问题描述
Django by-default实现用户名区分大小写,现在用于身份验证我已经编写了自己的身份验证后端
,以便在身份验证时处理不区分大小写的用户名。
Django by-default implements username as case sensitive, now for authentication I have written my own Authentication Backend
to handle case insensitive usernames while authentication.
如下所示: http://blog.shopfiber.com/?p=220
现在,问题是:
我有各种各样的视图和util方法,比较用户名
到一些蜇。
I have various views and util methods which compares username
to some stings.
ie
request.user.username == username_from_some_other_system_as_str
现在,如果用户名是 yugal
然后:
Now, if username is yugal
then:
request.user.username == 'Yugal' # Returns False
现在,它应该返回 True
[我想要实现]
Now, it should return True
[ What I wanted to achieve ]
为了我记得从 C ++
days,运算符重载
。
但我不认为这样做只是为了django的 auth用户
将是一个好主意,因为 auth user
与 django
紧密绑定。
此外,重载 ==
将使整个类不区分大小写,而不仅仅是用户名
For that I remember from C++
days, Operator Overloading
.
But I don't think simply doing that for django's auth user
would be a good idea, since auth user
is tightly bound with django
.
Also, overloading ==
will make it case-insensitive for the whole class not just for the username
field.
所以,即使在比较时,我该怎么去讨论这个用户名
case-insensitivity。
So, how should I go about this username
case-insensitivity even when compared throughout.
注意:
-
创建一个
get_username
返回小写用户名的方法是不可能的,因为它需要重新确定所有代码才能使用它。您可以为代码执行一次,但如果您使用第三方django应用程序,则不可能。
Creating a
get_username
method that returns lower-case username always is not possible, since it would require all code to be re-factored to use it. You can do it for your code for once, but not possible if you are using 3rd party django apps.
我知道用户。 username.lower()= something.lower()
是可能的,但是容易出错,而不是在多开发人员设置中经常使用的写入解决方案。
I know user.username.lower() = something.lower()
is possible but is bug prone and not the write solution for something so often used in a multi-developer setup.
尽可能使用 SomeModel.objects.filter(username__iexact = username)
。但是,这仍然使系统容易受到任何不了解的开发人员的错误。
I have used SomeModel.objects.filter(username__iexact=username)
, wherever possible. But that still leaves the system vulnerable to a mistake by any of un-aware developer.
===== ===============================
======================================
在概念上解决了解决方案,但无法使其工作(帮助):
####### 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
用于将从数据库接收的值转换为python中的 unicode
。但是,我想我的 to_python
没有被调用。
I assume to_python
is used to convert the value received from database to unicode
in python. But, I guess my to_python
is not getting called.
这也将确保第三方应用程序不区分大小写,不需要重新分解。它将其核心的
用户
修补。我将添加到我的第一个INSTALLED_APP
This will also ensure case-insensitivity in 3rd party apps and would not require any re-factoring. It will patch the
User
at its core. I will be adding this to__init__.py
of my firstINSTALLED_APP
我做错了什么?
推荐答案
对 User
模型进行了如此多的实验和最小化的影响,终于实现了。
[感谢先生。 @freakish 为不同的想法]
With so much experimenting and minimum effect on User
model, finally achieved it.
[ Thanks to Mr. @freakish for a different thought ]
这是:
############ 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
I tested it and it worked as expected. :D
所以,这里是 testcases :
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()))
数据库的隐含不区分大小写的查询
Implicit Case-insensitive queries for database
###################### 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')
产生相同的用户。
This will allow, User.objects.get(username='yugal')
& User.objects.get(username='YUGAl')
yield the same user.
这篇关于Django:用户名和密码用户名不区分大小写匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!