2

我正在使用 python-social-auth 和 django-rest-framework 来允许用户在我的应用程序中使用他们的社交帐户进行注册。

我的情况类似于这篇文章 用户不是在使用 facebook 登录后创建的(可能是同名案例)

我使用 django-rest-framework 的 TokenAuthentication 对用户进行身份验证

使用我的自定义用户模型时,当标头中有可用的 authtoken(用户已登录)时,创建的社交用户帐户将链接到其令牌按预期附加到请求的用户,但是当没有可用的令牌时,它无法创建新帐户。

但是当使用默认的 django 用户模型时,一切都按预期工作。我怀疑我没有正确配置我的自定义用户模型。

下面是我的设置文件,你可以看看,看看你能不能找出我做错了什么。

提前致谢。

我的设置文件

 REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework.authentication.TokenAuthentication',
    ),
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticatedOrReadOnly',
    ),
    'PAGINATE_BY': 10
 }

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.request',
    'social.apps.django_app.context_processors.backends',
)

SOCIAL_AUTH_FACEBOOK_KEY = os.environ.get('FB_APP_ID')
SOCIAL_AUTH_FACEBOOK_SECRET = os.environ.get('FB_APP_SECRET')
SOCIAL_AUTH_FACEBOOK_EXTENDED_PERMISSIONS = ['email']
SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']

SOCIAL_AUTH_USER_MODEL = 'users.FLUser'

SOCIAL_AUTH_TWITTER_KEY = os.environ.get('TWITTER_APP_ID')
SOCIAL_AUTH_TWITTER_SECRET = os.environ.get('TWITTER_APP_SECRET')

AUTHENTICATION_BACKENDS = (
    'social.backends.twitter.TwitterOAuth',
    'social.backends.facebook.FacebookOAuth2',
    'social.backends.facebook.Facebook2OAuth2',
    'django.contrib.auth.backends.ModelBackend',
)

SOCIAL_AUTH_PIPELINE = (
    'social.pipeline.social_auth.social_details',
    'social.pipeline.social_auth.social_uid',
    'social.pipeline.social_auth.auth_allowed',
    'social.pipeline.social_auth.social_user',
    'social.pipeline.user.get_username',
    'social.pipeline.social_auth.associate_by_email',
    'social.pipeline.user.create_user',
    'social.pipeline.social_auth.associate_user',
    'social.pipeline.social_auth.load_extra_data',
    'social.pipeline.user.user_details'
    # 'apps.users.pipeline.user_details',
)

定制经理

class FLUserManager(BaseUserManager):

    def _create_user(self, username, email, password,
                     is_staff, is_superuser, **extra_fields):
        """
        Creates and saves a User with the given username, email and password.
        """
        now = timezone.now()
        if not email:
            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=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=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):
        return self._create_user(username, email, password, True, True,
                                 **extra_fields)

自定义用户模型

class FLUser(AbstractBaseUser, PermissionsMixin):

    GENDER = (
        ('M', 'Male'),
        ('F', 'Female'),
    )
    email = models.EmailField(
        verbose_name=_('email address'),
        max_length=255,
        unique=True,
    )
    username = models.CharField(
        verbose_name=_('username'),
        max_length=30,
        unique=False,
        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(max_length=100)
    last_name = models.CharField(max_length=100)
    birthday = models.DateTimeField(
        blank=True,
        default=None,
        null=True
    )
    gender = models.CharField(
        max_length=1,
        choices=GENDER,
        default=None,
        null=True
    )
    avatar = models.ImageField(
        upload_to='media/avatars',
        blank=True,
        default=None,
        null=True
    )
    sm_avatar = models.URLField(
        blank=True,
        default=None,
        null=True,
        verbose_name=_('Social Media Avatar')
    )
    is_active = models.BooleanField(
        _('active'),
         default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.')
    )
    is_admin = models.BooleanField(default=False)

    objects = FLUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'username',]

    def is_authenticated(self):
        return True

    def get_full_name(self):
        return '''{} {}'''.format(self.first_name, self.last_name)

    def get_short_name(self):
        return self.first_name

    @property
    def is_staff(self):
        return self.is_admin

    def has_perm(self, perm, obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes, always
        return True

    def has_module_perms(self, app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes, always
        return True

    # On Python 3: def __str__(self):
    def __unicode__(self):
        return self.email

    def email_user(self, subject, message, from_email=None):
        """
        Sends an email to this User.
        """
        send_mail(subject, message, from_email, [self.email])

    class Meta:
        ordering = ('id', 'first_name',)
        verbose_name = _('user')
        verbose_name_plural = _('users')


@receiver(post_save, sender=FLUser)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

风景

@api_view(['POST'])
@permission_classes((AllowAny,))
@strategy()
def register_by_access_token(request, backend):
   backend = request.strategy.backend
   if backend.name == 'twitter':
      token = {
          'oauth_token': request.DATA.get('access_token'),
          'oauth_token_secret': os.environ.get('TWITTER_APP_OAUTH_SECRET'),
      }
   elif backend.name == 'facebook':
      token = request.POST.get('access_token')
   else:
      raise Response('Wrong backend type', status=HTTP_400_BAD_REQUEST)

   user = backend.do_auth(
       access_token=token,
       user=request.user.is_authenticated() and request.user or None
   )
   if user and user.is_active:
      login(request, user)
      user = UserAuthSerializer(user)
      return Response(user.data, status=HTTP_200_OK)
   else:
      return Response({'detail': 'Unable to authenticate user'}, status=HTTP_400_BAD_REQUEST)
4

1 回答 1

0

不确定这是否重要,但我认为您的继承对于您的自定义用户模型来说有点错误(mixin 出现在前面):

class FLUser(PermissionsMixin, AbstractBaseUser):
    ....
于 2015-02-14T02:37:38.683 回答