Django社交身份验证使用自定义模型创建新用户

问题描述

我正在尝试在使用自定义Django用户模型和django-rest-framework-social-oauth2作为社交身份验证软件包的应用程序上开发Facebook社交身份验证功能。我的自定义用户模型称为“帐户”,它继承自AbstractBaseUser类。帐户模型如下所示:

class Account(AbstractBaseUser):
  # Account model fields: 
  email = models.EmailField(verbose_name='email',max_length=60,unique=True)
  username = models.CharField(max_length=30,unique=True)
  first_name = models.CharField(max_length=30)
  last_name = models.CharField(max_length=30)
  date_joined = models.DateTimeField(verbose_name='date joined',auto_now_add=True)
  last_login = models.DateTimeField(verbose_name='last login',auto_now=True)
  is_admin = models.BooleanField(default=False)
  is_active = models.BooleanField(default=True)
  is_staff = models.BooleanField(default=False)
  is_superuser = models.BooleanField(default=False)

  # The user will log in with their email instead of username:
  USERNAME_FIELD = 'email'

  # Required fields when registering,other than the email:
  REQUIRED_FIELDS = ['username','first_name','last_name']

  # Telling the Account object how to use the account manager:
  objects = MyAccountManager()

处理创建新用户的功能称为“ create_user”,并在我的自定义书面MyAccountManager类中定义,该类扩展了Django BaseUserManager类。如下所示:

class MyAccountManager(BaseUserManager):
def create_user(self,email,username,first_name,last_name,password=None):
    # Checking to see if correct function parameters have been passed in: 
    if not email:
        raise ValueError('Users must have an email address')
    if not username:
        raise ValueError('Users must have a username')
    if not first_name:
        raise ValueError('Users must have a first name')
    if not last_name:
        raise ValueError('Users must have a last name')

    # Creating the new user:
    user = self.model(
        email = self.normalize_email(email),username = username,first_name = first_name,last_name = last_name,)
    user.set_password(password)
    user.save(using = self._db)
    
    return user

我已经设置了有效的django-rest-framework-social-oauth2网址,用于使用Facebook帐户创建新用户。 Django settings.py文件中的相关Facebook配置如下所示:

SOCIAL_AUTH_FACEBOOK_KEY = config('SOCIAL_AUTH_FACEBOOK_KEY')
SOCIAL_AUTH_FACEBOOK_SECRET = config('SOCIAL_AUTH_FACEBOOK_SECRET')

SOCIAL_AUTH_FACEBOOK_SCOPE = ['email']
SOCIAL_AUTH_FACEBOOK_PROFILE_EXTRA_PARAMS = { 'fields': 'id,name,email' }

我遇到的问题如下: 当使用Facebook社交登录的用户调用create_user函数时,Facebook没有提供create_user函数中必需的参数email,first_name和last_name,并且我得到了图像中所示的错误消息。该错误消息指出以下内容:

create_user()缺少2个必需的位置参数:“ first_name”和“ last_name”

Error Message from Django

有人知道我将如何从Facebook访问这些附加参数(电子邮件,名字,姓氏),以便将正确的参数传递给create_user函数?


其他信息

在实施管道建议时,我仍然遇到相同的问题,即自定义create_user函数缺少first_name和last_name参数。我认为发生这种情况的原因是由于在create_user之后调用了建议的管道cleanup_social_account函数,在本例中,first_name和last_name都是必填字段,因此,如果未在数据库中提供用户对象,则无法在数据库中创建用户对象调用create_user函数的时间。

由于建议的自定义管道中的以下功能,我收到此错误:

social_core.pipeline.user.create_user

social_core已安装库中用于此功能的代码如下:

def create_user(strategy,details,backend,user=None,*args,**kwargs):
  if user:
      return {'is_new': False}

  fields = dict((name,kwargs.get(name,details.get(name)))
                for name in backend.setting('USER_FIELDS',USER_FIELDS))
  if not fields:
      return

  return {
      'is_new': True,'user': strategy.create_user(**fields)
  }

传递给上述函数的details参数包含我需要的值(first_name和last_name)。但是,创建变量时,实际上并没有将它们添加到fields变量中。字段变量显示在上方,并由以下内容定义:

fields = dict((name,USER_FIELDS))

摘要: 问题似乎是first_name和last_name没有出现在backend.settings('USER_FIELDS',USER_FIELDS)中,因此没有被添加到fields变量中,因此没有被传递到strategy.create_user(** fields) )。

解决方法

因此,当我刚刚从Facebook获得姓名和电子邮件时,social_auth会自动为我填充这些字段。它知道要输入first_name和last_name。由于它似乎不适合您,您可以创建一个自定义管道功能。

settings.py:

SOCIAL_AUTH_PIPELINE = (
'social_core.pipeline.social_auth.social_details','social_core.pipeline.social_auth.social_uid','social_core.pipeline.social_auth.auth_allowed','social_core.pipeline.social_auth.social_user','social_core.pipeline.user.get_username','social_core.pipeline.social_auth.associate_by_email','social_core.pipeline.user.create_user',# YOUR CUSTOM PIPELINE FUNCTION HERE.  I CREATED A FILE/MODULE
# NAMED pipeline.py AND STUCK IT IN THERE.  MAKE SURE TO PUT THIS
# AFTER CREATE USER.
'path.to.custom.pipeline.cleanup_social_account','social_core.pipeline.social_auth.associate_user','social_core.pipeline.social_auth.load_extra_data','social_core.pipeline.user.user_details',

pipeline.py:

def cleanup_social_account(backend,uid,user=None,*args,**kwargs):
"""
3rd party: python-social-auth.

Social auth pipeline to cleanup the user's data.  Must be placed
after 'social_core.pipeline.user.create_user'.
"""

# Check if the user object exists and a new account was just created.
if user and kwargs.get('is_new',False):

    *** THIS IS UNTESTED,BUT FACEBOOK'S DATA SHOULD COME INTO THE DETAILS KWARG ***
    user.first_name = kwargs['details']['first_name']
    user.last_name = kwargs['details']['last_name']
    user.save()

return {'user': user}

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...