我正在尝试在使用自定义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”
有人知道我将如何从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, kwargs.get(name, details.get(name)))
for name in backend.setting('USER_FIELDS', USER_FIELDS))
摘要: 问题似乎是first_name和last_name没有出现在backend.settings('USER_FIELDS',USER_FIELDS)中,因此没有被添加到fields变量中,因此没有被传递到strategy.create_user(** fields) )。
答案 0 :(得分:0)
因此,当我刚刚从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}