Django-rest-auth registration with both Email and username (请仔细阅读说明)

Django-rest-auth registration with both Email and username (Please read the explanation carefully)

我想要发生什么 我正在使用 Django rest auth, 1) 我希望用户能够 signup/register 询问他们的电子邮件、用户名和密码。 2) 当用户要登录时,将询问电子邮件。

注意事项 1)电子邮件对我很重要,因为它将被验证以了解用户是否真实 2) 用户名​​对我来说很重要,因为唯一的用户名将能够轻松访问具有样式的用户的个人资料,例如 www.website.com/。我希望能够使用用户名做类似的事情,这就是为什么它很重要

发生了什么 1) 我注意到我不能同时使用电子邮件和用户名,或者我不知道如何有效地设置身份验证后端

我的代码

settings.py

INSTALLED_APPS = [
    ...
    'rest_framework',
    'rest_framework.authtoken',
    'rest_auth',
    'rest_auth.registration',
    'allauth',
    'allauth.account',
    ...
    'accounts',
]

ACCOUNT_USER_MODEL_USERNAME_FIELD = None
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_USERNAME_REQUIRED = False
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_USER_EMAIL_FIELD = 'email'
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_LOGOUT_ON_GET = True

models.py

class UserManager(BaseUserManager):
    """
    The User Manager
    """
    def _create_user(self, email, fullname, password, is_staff, is_superuser, **extra_fields):
        if not email:
            raise ValueError('Users must have an email address')
        now = timezone.now()
        email = self.normalize_email(email)
        fullname = fullname
        user = self.model(
            email=email,
            fullname=fullname,
            is_staff=is_staff,
            is_active=True,
            is_superuser=is_superuser,
            last_login=now,
            date_joined=now,
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, fullname, password, **extra_fields):
        return self._create_user(email, fullname, password, False, False, **extra_fields)

    def create_superuser(self, email, fullname, password, **extra_fields):
        user = self._create_user(email, fullname, password, True, True, **extra_fields)
        user.save(using=self._db)
        return user


class User(AbstractBaseUser, PermissionsMixin):
    username = None
    email = models.EmailField(max_length=254, unique=True)
    fullname = models.CharField(max_length=250)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    slug = models.SlugField(max_length=255, unique=True, blank=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['fullname']

    objects = UserManager()

    def __str__(self):
        return self.email

我将用户名设置为 none 因为当我设置它时它不起作用

序列化器

class CustomRegisterSerializer(RegisterSerializer):
    '''
    a custom serializer that overides the default rest-auth, and for
    the user to register himself
    '''
    username = None
    email = serializers.EmailField(required=True)
    password1 = serializers.CharField(write_only=True)
    fullname = serializers.CharField(required=True)
    slug = serializers.SlugField(read_only=True)

    def get_cleaned_data(self):
        super(CustomRegisterSerializer, self).get_cleaned_data()

        return {
            'password1': self.validated_data.get('password1', ''),
            'email': self.validated_data.get('email', ''),
            'fullname': self.validated_data.get('fullname', ''),
        }

查看

class CustomRegisterView(RegisterView):
    '''
    a custom register view that overrides the rest-auth's default 
    '''
    permission_classes = [AllowAny]
    queryset = User.objects.all()

拜托,我花了很长时间才解决这个问题,如果有人能帮助我,我将不胜感激。谢谢

要准确解决您指出的问题,另一种解决方案是 django-graphql-auth。不影响django-rest-framework,两者可以一起使用

I want the users to be able to signup/register asking for their Email, username, and password.

通过提供 emailusernamepassword1password2 进行注册。但是您可以在设置中添加更多 字段或更改

When the user wants to log in, the email is what will be asked.

用户可以使用emailusername登录。但同样,您可以在设置中更改它,如果需要,只允许电子邮件。

The email is important to me because it will be verified to know is the user is real.

确实有邮箱验证流程,还有二次邮箱验证。

I noticed I cannot use both email and username at the same time

在 django-graphql-auth 中你可以。

例子

安装完成后,按照设置指南,您可以像这个例子一样制作一个简单的流程。

注册

注册是通过像这样简单地发送一个 graphql 突变来完成的(如果你不知道什么是 graphql 或如何使用 graphql,quickstart guide 教你):

mutation {
  register(
    email:"user_email@email.com",
    username:"user_username",
    password1: "somerandompassword",
    password2:"somerandompassword"
  ) {
    success,
    errors,
    token,
    refreshToken
  }
}

然后,创建一个模型 UserStatus,与您的用户模型相关:

from django.contrib.auth import get_user_model

u = get_user_model().objects.get(username="user_username")

# check the user status
u.verified # False
u.archived # False
u.secondary_email # "" 

验证帐户

在注册期间,向用户发送了一封电子邮件,其中 link 包含令牌。

在你的前端,你可以使用来自 url 的令牌发送其他突变:

mutation {
  verifyAccount(
    token:"<TOKEN HERE>",
  ) {
    success, errors
  }
}

验证成功后,您的用户状态为:

u.verified # True

演示

这是此流程的演示视频:

(我是作者。)