1

我正在构建一个新的 Djnago 应用程序。我正在使用 django-rest-auth ( http://django-rest-auth.readthedocs.io/en/latest/index.html ) 进行登录和注册。但是,它存在一些问题。

确切的问题是:

  1. 对于登录:当我尝试使用表单和原始数据选项通过 API 登录时,登录不成功。它给出了"non_field_errors": ["User account is disabled."]错误。
  2. 注册:当我填写数据并注册时,它给了我错误,但是数据保存在数据库中。

现在我做了很多事情,我不确定我做错了什么,我按照以下顺序做事

  1. 创建了一个新的 Django 休息项目
  2. 创建了一个名为 myauth 的应用程序来自定义用户模型,如下所示:

    class UserManager(BaseUserManager):
    
    def _create_user(self, username, email, password, is_staff, is_superuser, **extra_fields):
    now = timezone.now()
    if not username:
     raise ValueError(_('The given username must be set'))
    email = self.normalize_email(email)
    user = self.model(username=username, email=email,
         is_staff=is_staff, is_active=False,
         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=None, password=None, **extra_fields):
    return self._create_user(username, email, password, False, False,
             **extra_fields)
    
    def create_superuser(self, username, email, password, **extra_fields):
    user=self._create_user(username, email, password, True, True,
             **extra_fields)
    user.is_active=True
    user.save(using=self._db)
    return user
    
    
    class User(AbstractBaseUser, PermissionsMixin):
       username = models.CharField(_('username'), max_length=30, unique=True,
       help_text=_('Required. 30 characters or fewer. Letters, numbers and @/./+/-/_ characters'),
       validators=[
       validators.RegexValidator(re.compile('^[\w.@+-]+$'), _('Enter a valid username.'), _('invalid'))
       ])
       first_name = models.CharField(_('first name'), max_length=30, blank=True, null=True)
       last_name = models.CharField(_('last name'), max_length=30, blank=True, null=True)
       email = models.EmailField(_('email address'), max_length=255, unique=True)
       is_staff = models.BooleanField(_('staff status'), default=False,
       help_text=_('Designates whether the user can log into this admin site.'))
       is_active = models.BooleanField(_('active'), default=False,
       help_text=_('Designates whether this user should be treated as active. Unselect this instead of deleting accounts.'))
       date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
       receive_newsletter = models.BooleanField(_('receive newsletter'), default=False)
       birth_date = models.DateField(auto_now=False, null=True)
       address = models.TextField(max_length=500, null=True)
       phone_regex = RegexValidator(regex=r'^\+?1?\d{9,15}$', message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.")
       phone_number = models.CharField(validators=[phone_regex], blank=True, max_length=20) # validators should be a list
    
    
      USERNAME_FIELD = 'email'
      REQUIRED_FIELDS = ['username',]
    
      objects = UserManager()
    
      class Meta:
       verbose_name = _('user')
       verbose_name_plural = _('users')
    
      def get_full_name(self):
        full_name = '%s %s' % (self.first_name, self.last_name)
        return full_name.strip()
    
     def get_short_name(self):
        return self.first_name
    
    def email_user(self, subject, message, from_email=None):
        send_mail(subject, message, from_email, [self.email]) 
    
  3. 在 settings.py 中添加它AUTH_USER_MODEL = 'myauth.User'并在 admin.py 中注册它。迁移创建了具有上述列的所有表。

  4. 我想修改注册,以便能够注册名字和姓氏以及用户名、电子邮件和密码。还能够使用电子邮件而不是用户名登录。因此,我的用户模型和 settings.py 中可能存在冲突代码。为此,在我的 serializers.py 中,我添加了以下代码:

     from myauth.models import User
    
     from allauth.account import app_settings as allauth_settings
     from allauth.utils import email_address_exists
     from allauth.account.adapter import get_adapter
     from allauth.account.utils import setup_user_email
    
     #Custom registration to store first and last name along with email and password 
     class RegisterSerializer(serializers.Serializer):
     email = serializers.EmailField(required=allauth_settings.EMAIL_REQUIRED)
     first_name = serializers.CharField(required=True, write_only=True)
     last_name = serializers.CharField(required=True, write_only=True)
     password1 = serializers.CharField(required=True, write_only=True)
     password2 = serializers.CharField(required=True, write_only=True)
    
     def validate_email(self, email):
         email = get_adapter().clean_email(email)
         if allauth_settings.UNIQUE_EMAIL:
           if email and email_address_exists(email):
            raise serializers.ValidationError(
                _("A user is already registered with this e-mail address."))
     return email
    
     def validate_password1(self, password):
       return get_adapter().clean_password(password)
    
     def validate(self, data):
       if data['password1'] != data['password2']:
        raise serializers.ValidationError(
            _("The two password fields didn't match."))
      return data
    
     def get_cleaned_data(self):
       return {
        'first_name': self.validated_data.get('first_name', ''),
        'last_name': self.validated_data.get('last_name', ''),
        'password1': self.validated_data.get('password1', ''),
        'email': self.validated_data.get('email', ''),
      }
    
     def save(self, request):
       adapter = get_adapter()
       user = adapter.new_user(request)
       self.cleaned_data = self.get_cleaned_data()
       adapter.save_user(request, user, self)
       setup_user_email(request, user, [])
       user.save()
       return user
    
  5. 我的 settings.py 如下所示:

    INSTALLED_APPS = (
     'django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'rest_framework',
     'rest_framework.authtoken',
     'rest_auth',
     'allauth',
     'allauth.account',
     'rest_auth.registration',
     'myauth',
     'swarms_app'
    )
    
    AUTH_USER_MODEL = 'myauth.User'
    
    MIDDLEWARE_CLASSES = (
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
     'django.middleware.csrf.CsrfViewMiddleware',
     'django.contrib.auth.middleware.AuthenticationMiddleware',
     'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
     'django.contrib.messages.middleware.MessageMiddleware',
     'django.middleware.clickjacking.XFrameOptionsMiddleware',
     'django.middleware.security.SecurityMiddleware',
     )
    
     ROOT_URLCONF = 'urls'
    
    TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
          },
        },
       ]
    
       WSGI_APPLICATION = 'config.wsgi.application' 
    
    DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  
        'NAME': 'new_swarms',
        'USER': 'root',
        'PASSWORD': 'root',
        'HOST': 'localhost',   # Or an IP Address that your DB is hosted on
        'PORT': '3306',
    }
    }
    
    
    STATIC_URL = '/static/'
    
    ##############################################################
    ## All the customization as taken from original swarms code ## 
    ##############################################################
    
    
    #This is added to use custon registration serializer which stores first and last name along with email and password
    REST_AUTH_REGISTER_SERIALIZERS = {
        'REGISTER_SERIALIZER': 'myauth.serializers.RegisterSerializer',
    } 
    
    REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.BasicAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.TokenAuthentication',
    )
    }
    
    #Following is added to enable registration with email instead of username
    AUTHENTICATION_BACKENDS = (
    # Needed to login by username in Django admin, regardless of `allauth`
    "django.contrib.auth.backends.ModelBackend",
    
    # `allauth` specific authentication methods, such as login by e-mail
    "allauth.account.auth_backends.AuthenticationBackend",
    )
    
    #This is required otherwise it asks for email server
    EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
    
    ACCOUNT_AUTHENTICATION_METHOD = 'email'
    ACCOUNT_EMAIL_REQUIRED = True   
    ACCOUNT_USERNAME_REQUIRED = False
    

我创建的自定义模型似乎有效,因为在迁移时它创建了包含所有提到字段的表。我什至可以在我的管理界面中看到它。

这里出了什么问题?

4

2 回答 2

1
user = self.model(username=username, email=email,
     is_staff=is_staff, is_active=False,
     is_superuser=is_superuser, last_login=now,
     date_joined=now, **extra_fields)

您已将 this(is_active) 设置为默认“假”。我认为在注册时会禁用用户。这就是原因,在登录时,您会收到“禁用”响应。

请在注册或创建新帐户时使 is_active = true。

于 2016-06-13T07:38:06.827 回答
1

当注册和登录开始工作时,我确实升级了 Django 版本并重新安装了 django-rest-auth 和 django-allauth,但并不完全正确。

通过 API,只有在使用原始数据时才有可能,而不是在使用 HTML 表单时,请参阅截图:

在此处输入图像描述

注销仍然中断。

在此处输入图像描述

对这两个问题有进一步的答案吗?通过 HTML注销和启用?

于 2016-06-13T09:13:08.317 回答