2016-12-05 162 views
1

使用Django 1.10我想在用户名中允许\字符,因为我在使用'django.contrib.auth.middleware.RemoteUserMiddleware'的Windows环境中工作,并且远程用户作为域\用户名(我不想删除域在某些业务逻辑中使用)。Django覆盖ASCIIUsernameValidator

我可以通过修改行regex = r'^[\[email protected]+-]+$'改变Django的\的contrib \权威性\ validators.py容易够了,都希望的影响是regex = r'^[\[email protected]+-\\]+$'不过,我认为一个可以很容易地覆盖这个类,但我失败了。

我发现一些有用的链接(和许多其他类似这里SO):

https://stackoverflow.com/a/39820162/4872140

https://stackoverflow.com/a/1214660/4872140

https://docs.djangoproject.com/en/1.10/releases/1.10/#official-support-for-unicode-usernames https://docs.djangoproject.com/en/1.10/ref/contrib/auth/#django.contrib.auth.models.User.username_validator

但信息是过时的,或者没有按不完全显示/完全如何解决我的问题(在最后两个的情况下)。我很喜欢这款应用,所以改变AUTH_USER_MODEL并不吸引人。 settings.py:

AUTH_USER_MODEL = 'myapp.MyUser' 

无论如何我尝试了,想我或许可以对用户模型等,其导致错误以下使用代理服务器“不能代理的交换模式‘myapp.DomainUser’”:

class DomainASCIIUsernameValidator(ASCIIUsernameValidator): 
    regex = r'^[\[email protected]+-\\]+$' 

class DomainUser(User): 
    username_validator = DomainASCIIUsernameValidator() 

    class Meta: 
     proxy = True 

是否有一种方法可以用户模型保持不变的方式在ASCIIUsernameValidator(和UnicodeUsernameValidator)中替换正则表达式。如果您按照https://docs.djangoproject.com/en/1.10/ref/contrib/auth/#django.contrib.auth.models.User.username_validator中所描述的方式对用户模型进行子类化,您是否坚持在AUTH_USER_MODEL中指定该模型?

我已阅读https://groups.google.com/forum/#!topic/django-developers/MBSWXcQBP3k/discussion的讨论,感觉从一开始就创建自定义用户可能会成为默认情况。

回答

4

我花了一整天的时间和许多不同的答案来得到这个工作。我将代码分成不同的部分。首先,我们有我们的验证:

validators.py

from django.contrib.auth.validators import UnicodeUsernameValidator 
from django.utils.translation import ugettext_lazy as _ 


class DomainUnicodeUsernameValidator(UnicodeUsernameValidator): 
    """Allows \.""" 
    regex = r'^[\[email protected]+-\\]+$' 
    message = _(
     'Enter a valid username. This value may contain only letters, ' 
     'numbers, and \/@/./+/-/_ characters.' 
    ) 

我加改变的消息也说\是允许的。您也可以轻松添加DomainASCIIUsernameValidator。

models.py

from django.contrib.auth.models import User 

from .validators import DomainUnicodeUsernameValidator 


class DomainUser(User): 
    class Meta: 
     proxy = True 

    def __init__(self, *args, **kwargs): 
     self._meta.get_field(
      'username' 
     ).validators[0] = DomainUnicodeUsernameValidator() 

     super().__init__(*args, **kwargs) 

这抓住了我们之前设置的验证。它还代理默认用户并为用户名字段设置验证器。您可以设置验证器作为一个列表,包括新的验证和最大长度校验(这可能是在情况下,为了改变更安全)。

forms.py

from django.contrib.auth.forms import UserChangeForm 
from django.utils.translation import ugettext_lazy as _ 

from .models import DomainUser 


class DomainUserChangeForm(UserChangeForm): 
    class Meta(UserChangeForm.Meta): 
     model = DomainUser 
     help_texts = { 
      'username': _('Required. 150 characters or fewer. Letters, digits and \/@/./+/-/_ only.'), # NOQA 
     } 

在这里,我延长UserChangeForm和设置模式,使用用户名验证变更代理模型。

如果您希望允许用户使用\添加用户名,那么您还需要以类似的方式更改UserAddForm。

最后,在admin.py

from django.contrib import admin 
from django.contrib.auth.admin import UserAdmin 
from django.contrib.auth.models import User 

from .forms import DomainUserChangeForm 


class DomainUserAdmin(UserAdmin): 
    form = DomainUserChangeForm 


admin.site.unregister(User) 
admin.site.register(User, DomainUserAdmin) 

我们设定的形式为我们的管理员将在Django管理页面中使用。然后取消设置用户管理,并将其替换为我们的自定义DomainUserAdmin。

+0

哇!我刚刚开始一个新项目,我会在第二天左右通过这个项目给大家一个镜头。 – AMG

+0

如果您要开始一个新项目,我会建议创建一个新的用户模型。他们甚至推荐它[链接](https://docs.djangoproject.com/zh/dev/topics/auth/customizing/#substotation-a-custom-user-model): _如果你正在开始一个新项目,强烈建议设置一个自定义用户模型,即使默认的用户模型对您来说已经足够。此模型的行为与默认用户模型的行为相同,但如果需要,您可以在将来自定义它:_。 –