使用用户名和电子邮件注册,并且仅使用电子邮件登录

时间:2019-12-13 19:40:47

标签: django django-rest-framework django-rest-auth

我正在创建一个使用Django-rest-auth请求用户名和电子邮件的登录名,该电子邮件是密钥,因为它将用于登录用户。但是用户名在我的应用程序中也很重要,因为当搜索用户时,我想做类似“ accounts //”的事情。

在尝试执行此操作时,我按照以前的帖子中的建议添加了一个后端。

请问我该怎么办,所以注册时可以输入我的用户名和电子邮件,但是登录时我仅使用电子邮件?

backend.py

class EmailAndUsernameBackend(ModelBackend):
    """
    this model backend would help me use both username and email,
    remember to overide your AUTHENTICATION_BACKENDS to this one
    """
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()

        if username is None:
            username = kwargs.get(UserModel.USERNAME_FIELD)
        try:
            user = UserModel.objects.get(Q(email=username) | Q(username=username))
        except UserModel.DoesNotExist:
            UserModel().set_password(password)
        else:
            if user.check_password(password) and self.user_can_authenticate(user):
                return user

在我的settings.py中,除了已安装的应用程序和身份验证后端外,我还有:

AUTHENTICATION_BACKENDS = (
    # 'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
    'core.backends.EmailAndUsernameBackend',
)

# to use old_password when setting a new password
OLD_PASSWORD_FIELD_ENABLED = True
LOGOUT_ON_PASSWORD_CHANGE = False

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

# UNSURE
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_LOGIN_ATTEMPTS_LIMIT = 5
ACCOUNT_LOGIN_ATTEMPTS_TIMEOUT = 86400 # 1 day in seconds
ACCOUNT_LOGOUT_REDIRECT_URL ='/accounts/login/'
LOGIN_REDIRECT_URL = '/accounts/profile'
SOCIALACCOUNT_EMAIL_VERIFICATION = 'none'

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_PORT = 587
EMAIL_HOST_USER = 'opedoetester@gmail.com'
EMAIL_HOST_PASSWORD = '9ja4lifE'
DEFAULT_FROM_EMAIL = 'opedoetester@gmail.com'
DEFAULT_TO_EMAIL = EMAIL_HOST_USER

EMAIL_CONFIRMATION_AUTHENTICATED_REDIRECT_URL = '/'

REST_AUTH_SERIALIZERS = {
    "USER_DETAILS_SERIALIZER": "accounts.api.serializers.CustomUserDetailsSerializer",
    'LOGIN_SERIALIZER': 'accounts.api.serializers.LoginSerializer',
}

REST_AUTH_REGISTER_SERIALIZERS = {
    "REGISTER_SERIALIZER": "accounts.api.serializers.CustomRegisterSerializer",
}

models.py

class UserManager(BaseUserManager):

  def _create_user(self, username, email, fullname, password, is_staff, is_superuser, **extra_fields):
    if not email:
        raise ValueError('Users must have an email address')
    now = timezone.now()
    username = username
    email = self.normalize_email(email)
    fullname = fullname
    user = self.model(
        email=email,
        username=username,
        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, username, email, fullname, password, **extra_fields):
    return self._create_user(username, email, fullname, password, False, False, **extra_fields)

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


class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=50)
    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()

serializers.py


class CustomRegisterSerializer(RegisterSerializer):
    '''
    a custom serializer that overides the default rest-auth, and for
    the user to register himself
    '''
    username = serializers.CharField(write_only=True)
    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', ''),
            'username': self.validated_data.get('username', ''),
            'email': self.validated_data.get('email', ''),
            'fullname': self.validated_data.get('fullname', ''),
        }

当我尝试以上方法时,我得到:

Traceback:

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\django\core\handlers\exception.py" in inner
  34.             response = get_response(request)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\django\core\handlers\base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\django\views\decorators\csrf.py" in wrapped_view
  54.         return view_func(*args, **kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\django\views\generic\base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\django\utils\decorators.py" in _wrapper
  45.         return bound_method(*args, **kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\django\views\decorators\debug.py" in sensitive_post_parameters_wrapper
  76.             return view(request, *args, **kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_auth\registration\views.py" in dispatch
  46.         return super(RegisterView, self).dispatch(*args, **kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\views.py" in dispatch
  505.             response = self.handle_exception(exc)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\views.py" in handle_exception
  465.             self.raise_uncaught_exception(exc)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\views.py" in raise_uncaught_exception
  476.         raise exc

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\views.py" in dispatch
  502.             response = handler(request, *args, **kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\generics.py" in post
  190.         return self.create(request, *args, **kwargs)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_auth\registration\views.py" in create
  64.         serializer.is_valid(raise_exception=True)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\serializers.py" in is_valid
  235.                 self._validated_data = self.run_validation(self.initial_data)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\serializers.py" in run_validation
  430.         value = self.to_internal_value(data)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_framework\serializers.py" in to_internal_value
  489.                     validated_value = validate_method(validated_value)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\rest_auth\registration\serializers.py" in validate_username
  177.         username = get_adapter().clean_username(username)

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\allauth\account\adapter.py" in clean_username
  264.             if filter_users_by_username(username).exists():

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\allauth\account\utils.py" in filter_users_by_username
  361.             for u in username]

File "D:\Opeodedeyi\Documents\Django\WORK IN PROGRESS\creative-api\venv\lib\site-packages\allauth\account\utils.py" in <listcomp>
  361.             for u in username]

Exception Type: TypeError at /api/accounts/signup/
Exception Value: unsupported operand type(s) for +: 'NoneType' and 'str'

注意:我正在使用Django rest auth来认证用户

0 个答案:

没有答案