【问题标题】:How to customize username validation如何自定义用户名验证
【发布时间】:2017-12-30 03:00:52
【问题描述】:

我正在尝试为 django.contrib.auth 用户模型自定义用户名验证。它说Usernames may contain alphanumeric, _, @, +, . and - characters.,但我想这样做,如果用户使用@, ., -, + 创建用户名,它将无效。我将如何覆盖此验证,以便在用户创建用户名时使用我的自定义验证而不是原始的 UnicodeUsernameValidator

我正在使用我自己的自定义用户模型,但我继承自 AbstractBaseUser 有没有简单的方法来添加我的用户名验证?

【问题讨论】:

    标签: python django


    【解决方案1】:

    您可以在模型类上设置 username_validator 属性:

    指向用于验证用户名的验证器实例。默认为validators.UnicodeUsernameValidator

    要更改默认用户名验证器,您可以继承User 模型并将此属性设置为不同的验证器实例。例如,使用 ASCII 用户名:

    from django.contrib.auth.models import User
    from django.contrib.auth.validators import ASCIIUsernameValidator
    
    class CustomUser(User):
        username_validator = ASCIIUsernameValidator()
    

    【讨论】:

    • 所以我可以用我自己的函数替换 ASCIIUsernameValidator() 吗?
    • 一旦我有了自定义的username_validator,它会自动验证用户名而无需调用任何函数?
    • 是的。你为什么不试试呢?
    • 我会的!非常感谢
    • 如果我们创建了username_validator = validate_username(),我们是否不需要像示例中那样有一个用户名参数,所以它会是username_validator = validate_username(username)
    【解决方案2】:

    假设您在 users 应用程序中工作,并且您的自定义用户模型的名称是 CustomUser,它位于 users/models.py 中。如果您不想在用户名中允许 @, ., -, +,则创建一个 forms.py,如下所示:

    users/forms.py

    from django.contrib.auth.forms import UserCreationForm, UserChangeForm
    from .models import CustomUser
    
    class CustomUserCreationForm(UserCreationForm):
        class Meta(UserCreationForm.Meta):
            model = CustomUser
            fields = ('username', 'first_name', 'last_name', 'email')
    
        def clean(self):
            cleaned_data = super(CustomUserCreationForm, self).clean()
            username = cleaned_data.get('username')
            if ('@', '.', '-', '+') in username:
                self.add_error('username', 'Symbols @/./-/+ are not allowed in username.')
            return cleaned_data
    
    # same for UserChangeForm
    class CustomUserChangeForm(UserChangeForm):
        class Meta(UserChangeForm.Meta):
            model = CustomUser
            fields = ('username', 'first_name', 'last_name')
            # Removed email field. Anyone won't want to change email after registering. Go as you like.
    
        def clean(self):
            cleaned_data = super(CustomUserChangeForm, self).clean()
            username = cleaned_data.get('username')
            if ('@', '.', '-', '+') in username:
                self.add_error('username', 'Symbols @/./-/+ are not allowed in username.')
            return cleaned_data
    

    如果有人尝试在用户名中使用@, ., -, + 注册,则会显示您的自定义错误消息。

    要更改 Django 默认描述 Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.,您的 models.py 应如下所示:

    users/models.py

    from django.contrib.auth.models import AbstractUser
    from django.db import models
    from django.contrib.auth import get_user_model
    from django.contrib.auth.validators import UnicodeUsernameValidator
    
    User = get_user_model
    
    class CustomUser(AbstractUser):
        username_validator = UnicodeUsernameValidator()
    
        username = models.CharField(
            "Username",
            max_length = 150,
            unique = True,
            help_text = ("Required. 150 characters or fewer. Letters, and digits only."),
            # customize the above string as you want
            validators = [username_validator],
            error_messages = {
                'unique': ("A user with that username already exists."),
            },
        )
        email = models.EmailField(max_length=254, blank=False, unique = True)
        first_name = models.CharField(max_length = 30, blank = False)
        last_name = models.CharField(max_length = 50, blank = False)
    

    别忘了检查您的 views.py 和模板。

    users/views.py

    from django.contrib.messages.views import SuccessMessageMixin
    from django.urls import reverse_lazy
    from django.views.generic import CreateView
    from .forms import CustomUserCreationForm
    from .models import CustomUser
    ...
    
    # Create your views here.
    class SignUpView(SuccessMessageMixin, CreateView):
        form_class = CustomUserCreationForm
        success_url = reverse_lazy('login')
        template_name = 'signup.html'
        success_message = 'Account was created successfully! Now Log In using your details.'
    ...
    

    用户/模板/signup.html

    ...
    
    {% block content %}
        <h2>Sign Up</h2>    
        <div>
            <form action="" method="POST">
                {% csrf_token %}
                {{ form.as_p }}
                <button class="" type="submit">Sign Up</button>
            </form>
        </div>
    {% endblock content %}
    ...
    

    这是您必须使用的最少 HTML。然后一切都会如你所愿。

    您可以添加更多自定义项(例如添加 Django 简洁表单,或在用户名/电子邮件中不区分大小写,或避免有时键入 email@gmail.comemail@googlemail.com 的用户重复。两者是相同的电子邮件。如果您不这样做t 包括检查,那么您的数据库中将有重复的用户。

    【讨论】:

    • 为最后一段干杯,我实际上学到了一些新东西。
    • @ImportError 非常感谢;)
    【解决方案3】:

    @Bytes 这是肮脏的伎俩,但有效:-

    def loginup(request):
        if request.method == "POST":
            username = request.POST['username']
            password = request.POST['password']
    
            #Manual code to Check whether username is valid or not
            try:
             myuser = User.objects.get(username=username)
            except:
                myuser = False
    
            if myuser == False:
                mypass = False
            else:
                mypass = myuser.check_password(password)
            user = auth.authenticate(username=username, password=password)
            if myuser != False:
                if user is not None:
                    auth.login(request, user)
                    messages.success(request, "You have Successfully Logged in")
                    return render(request, 'index.html')
                else:
                    messages.error(request, "Invalid Password")
                    return render(request, 'index.html')
            else:
                messages.error(request, "Invalid Username")
                return render(request, 'index.html')
        return render(request, 'index.html')
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-29
      • 2011-01-18
      • 1970-01-01
      • 2011-10-23
      • 1970-01-01
      相关资源
      最近更新 更多