Django REST Framework:强制小写用户名

Kev*_*ers 1 django django-rest-framework

我刚刚开始使用 Django REST Framework 进行一个业余项目,并且我试图强制所有用户名都小写(因为默认情况下它们区分大小写,并且我不希望人们拥有这样的用户kevinKevin) 。

这是我用来创建用户的代码:

# The serializer
class UserSerializer(serializers.ModelSerializer):
  password = serializers.CharField(write_only=True)
  token = serializers.SerializerMethodField()

  def create(self, validated_data):
    user = get_user_model().objects.create(**validated_data)
    user.set_password(validated_data['password'])
    user.save()
    return user

  def get_token(self, user):
    token = Token.objects.create(user=user)
    return token.key

  class Meta:
    model = get_user_model()
    fields = ('username', 'first_name', 'last_name', 'email', 'password', 'token')


# The View
class RegisterUserView(CreateAPIView):
  model = User
  serializer_class = UserSerializer
  permission_classes = (permissions.AllowAny, )


# And the URL pattern
urlpatterns = [
  path(r'user/register/', RegisterUserView.as_view()),
]
Run Code Online (Sandbox Code Playgroud)

因此,用户可以通过至少发布用户名和密码来创建一个新帐户user/register,并且在响应中他将获得完整的用户对象(包含名字、姓氏、电子邮件和身份验证令牌)。这有效。

但是,我正在努力强制使用小写用户名。例如,当我validated_data['username'] = validated_data['username'].lower()向序列化器中的 create 函数添加类似内容时,服务器在尝试创建具有相同用户名(但大小写不同)的用户时,只会生成错误 500“UNIQUE 约束失败:auth_user.username”。这当然不理想,错误 500。

我发现了一些添加自定义用户管理器的建议,如下所示:

lass MyUserManager(BaseUserManager):
    def get_by_natural_key(self, username):
        return self.get(username__iexact=username)
Run Code Online (Sandbox Code Playgroud)

但是,在通过自定义用户类将其连接并添加到设置文件后,这也没有执行任何操作。我仍然可以创建用户名中包含大写字母的用户。

让它正常工作的最简单的解决方案是什么?

Fli*_*rPA 6

如果您使用自定义用户模型并希望在整个 Django 中强制执行此操作,则可以创建自定义验证器。例如,创建一个validators.py作为models.py包含您的自定义用户模型的同级:

from django.core import validators
from django.utils.deconstruct import deconstructible
from django.utils.translation import gettext_lazy as _


@deconstructible
class MyUsernameValidator(validators.RegexValidator):
    """
    Validator for usernames.

    - Only ASCII lowercase letters, numbers and underscore are supported.
    - Must start with a letter.
    """
    regex = r'^[a-z][a-z0-9_]+$'
    message = _(
        'Enter a valid username. This value may contain only lowercase ASCII letters, '
        'numbers, and underscores. Must start with a letter.'
    )
    flags = 0
Run Code Online (Sandbox Code Playgroud)

然后在您的自定义用户模型中,包括:

from .validators import MyUsernameValidator

...

class User(AbstractBaseUser, PermissionsMixin):
    EMAIL_FIELD = 'email'
    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = [
        'first_name', 'last_name', 'email',
    ]

    username = models.CharField(
        max_length=16,
        unique=True,
        help_text=_(
            'Required. 16 characters or fewer. Lowercase letters, digits _ only; must start with a letter.'
        ),
        validators=[MyUsernameValidator()],
        error_messages={
            'unique': _("A user with that username already exists."),
        },
    )
Run Code Online (Sandbox Code Playgroud)

有一些稍微简单的方法,但是只要您坚持使用 ORM,这将通过 Django 强制执行。祝你好运!