终于明白了:
经过大量的实验和对
User模型的最小影响,终于实现了它。[感谢 @freakish先生 的不同想法]
这里是 :
############ username case-insensitivity ############class iunipre(unipre): def __init__(self, value): super(iunipre, self).__init__(value) self.value = value def __eq__(self, other): if isinstance(other, str) or isinstance(other, unipre): return self.value.lower() == other.lower() if isinstance(other, self.__class__): return other == self.valuedef custom_getattribute(self, name): val = object.__getattribute__(self, name) if name == "username": val = iunipre(val) return valdef auth_user_save(self, *args, **kwargs): # Ensures lowercase usernames username = self.username if username and type(username) in [unipre, str, iunipre]: self.username = username.lower() # only lower case allowed super(User, self).save(*args, **kwargs)User.__getattribute__ = custom_getattributeUser.save = MethodType(auth_user_save, None, User)#####################################################
我测试了它,并按预期工作。:D
因此,这是 测试用例 :
from django.test.testcases import TestCasedef 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 userclass 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, iunipre)) 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 == iunipre(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 clonefrom django.db.models.query import QuerySetQuerySet._filter_or_exclude = _filter_or_exclude#############################################################
这将允许
User.objects.get(username='yugal')并
User.objects.get(username='YUGAl')产生相同的用户。



