Django覆盖ASCIIUsernameValidator

AMG*_*AMG 4 django

使用Django 1.10我想在用户名中使用\字符,因为我在使用'django.contrib.auth.middleware.RemoteUserMiddleware'的Windows环境中工作,远程用户以域\用户名(我有)不希望删除域,因为它在某些业务逻辑中使用).

我可以很容易地改变django\contrib\auth\validators.py并通过修改该行regex = r'^[\w.@+-]+$'来获得所需的影响,regex = r'^[\w.@+-\\]+$'但我认为可以轻松覆盖这个类但我失败了.

我发现了一些有用的链接(以及其他很多类似的链接):

/sf/answers/2787411371/

/sf/answers/85026231/

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'
Run Code Online (Sandbox Code Playgroud)

无论如何我试过了,以为我可以在User模型上使用代理,如下所示导致错误"无法代理交换模型'myapp.DomainUser'":

class DomainASCIIUsernameValidator(ASCIIUsernameValidator):
    regex = r'^[\w.@+-\\]+$'

class DomainUser(User):
    username_validator = DomainASCIIUsernameValidator()

    class Meta:
        proxy = True
Run Code Online (Sandbox Code Playgroud)

有没有办法以用户模型保持原样的方式替换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上的讨论,感觉从一开始就创建自定义用户可能会成为默认情况.

小智 7

我花了整整一天的时间和许多不同的答案让这个工作起来.我把代码分成了不同的部分.首先,我们有验证器:

validators.py

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


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

我添加了对邮件的更改,也说\是允许的.您还可以轻松添加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)
Run Code Online (Sandbox Code Playgroud)

这抓住了我们之前设置的验证器.它还代理默认用户并为username字段设置验证器.您可以将验证器设置为列表以包含新验证器和最大长度验证器(如果订单更改,则可能更安全).

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
        }
Run Code Online (Sandbox Code Playgroud)

在这里,我正在扩展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)
Run Code Online (Sandbox Code Playgroud)

我们为管理员设置了将在django管理页面中使用的表单.然后取消设置用户管理员并将其替换为我们的自定义DomainUserAdmin.