Django rest-auth allauth 注册,带有电子邮件、名字和姓氏,没有用户名

Posted

技术标签:

【中文标题】Django rest-auth allauth 注册,带有电子邮件、名字和姓氏,没有用户名【英文标题】:Django rest-auth allauth registration with email, first and last name, and without username 【发布时间】:2016-08-22 23:08:30 【问题描述】:

我在我的 django 应用程序中使用 django-rest-auth 和 allauth 进行登录和注册。我没有为登录或注册编写任何额外的自己的单行代码。使用 emailid 和提供的密码注册成功。

我没有使用用户名进行身份验证,而是使用电子邮件。

在用于注册的可浏览 api 中,我得到以下信息:

除了这些字段之外,我还希望有 first_name 和 last_name(默认的 auth_user 表有这些列),以便我新创建的 auth_user 也设置这些字段以及电子邮件和散列密码。

我怎样才能做到这一点?这个可浏览的表单本身并不那么重要,但能够存储 first_name 和 last_name 是我主要需要的。

【问题讨论】:

在谷歌上搜索相同的东西会发现这里的头像有相似之处:github.com/pennersr/django-allauth/issues/1412。不得不提到它道歉:) 【参考方案1】:

    确保您的settings.py 文件中有ACCOUNT_USERNAME_REQUIRED = False

    对于first_namelast_name,您需要编写自定义RegisterSerializer (https://github.com/Tivix/django-rest-auth/blob/master/rest_auth/registration/serializers.py#L166)

这是serializers.py的示例代码

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

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

    settings.py 中确保添加以引用新的序列化器。

    REST_AUTH_REGISTER_SERIALIZERS = 
            'REGISTER_SERIALIZER': 'path.to.RegisterSerializer',
    
    

【讨论】:

就这些了吗?视图没有变化? 这很完美,用户保存了名字和姓氏!但是我收到一条错误消息,提示“用户”对象在 user.profile.save() 这一行没有属性“配置文件”.. 解决了!我将 user.profile.save() 更改为 user.save() 非常感谢!【参考方案2】:

您也可以只覆盖 RegisterSerializer 上的 custom_signup 方法,该方法旨在用于此目的。

from rest_auth.registration.serializers import RegisterSerializer
from rest_auth.registration.views import RegisterView
from rest_framework import serializers


class NameRegistrationSerializer(RegisterSerializer):

  first_name = serializers.CharField(required=False)
  last_name = serializers.CharField(required=False)

  def custom_signup(self, request, user):
    user.first_name = self.validated_data.get('first_name', '')
    user.last_name = self.validated_data.get('last_name', '')
    user.save(update_fields=['first_name', 'last_name'])


class NameRegistrationView(RegisterView):
  serializer_class = NameRegistrationSerializer

然后在您的 urls.py 中使用以下内容

url(r'^rest-auth/registration/name-registration/$', NameRegistrationView.as_view(), name="rest_name_register")

或在settings.py 中设置REGISTER_SERIALIZER

REST_AUTH_REGISTER_SERIALIZERS = 
    'REGISTER_SERIALIZER': 'path.to.RegisterSerializer',

【讨论】:

这是一个更好的方法。只是一个建议:如果您只想覆盖默认注册视图,则不需要视图。 该死的,你救了我的一天,伙计 这比接受的答案要好得多。【参考方案3】:

更优雅的解决方案是从 RegisterSerializer 继承并根据需要进行扩展。

class MyRegisterSerializer(RegisterSerializer):
    first_name = serializers.CharField(required=True, write_only=True)
    last_name = serializers.CharField(required=True, write_only=True)

    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

【讨论】:

使用最少的自定义代码就像一个魅力。我认为这是更优雅的解决方案。感谢发帖。 效果很好,但我觉得保存功能不是必须的,对吧? 是的,我也同意上面的评论。 我可以确认确实不需要保存功能,但也许您需要一个自定义适配器。 This answer explains a decent step-by-step.

以上是关于Django rest-auth allauth 注册,带有电子邮件、名字和姓氏,没有用户名的主要内容,如果未能解决你的问题,请参考以下文章

Django REST EmailAddress 匹配查询不存在

Django Ajax 403 仅在从自定义 localhost url 发布时

Django 无法使用 rest-auth/user/ 获取当前用户

Django REST-Auth 密码重置

django-allauth:如何修改电子邮件确认 url?

Django Rest Framework + Django-Allauth 密码重置/恢复