在没有用户名字段的自定义用户模型上使用Dj-Rest-Auth注册时出现FieldDoesNotExist错误

问题描述

我有一个自定义用户模型,该模型使用电子邮件进行登录,并且没有用户名字段。我正在尝试使用dj-rest-auth进行基于休息的用户注册登录

我在我的settings.py中放置了以下内容

SITE_ID = 1
AUTH_USER_MODEL = "users.User"
ACCOUNT_EMAIL_VERIFICATION = "none"
ACCOUNT_AUTHENTICATION_METHOD = 'email'
ACCOUNT_EMAIL_required = True
ACCOUNT_UNIQUE_EMAIL = True
ACCOUNT_USERNAME_required = False

AUTHENTICATION_BACKENDS = (
    "django.contrib.auth.backends.ModelBackend","allauth.account.auth_backends.AuthenticationBackend",)

REST_AUTH_REGISTER_SERIALIZERS = {
    'REGISTER_SERIALIZER': 'users.serializers.CustomregisterSerializer',}

当尝试通过注册端点进行注册时,执行甚至都不会到达我的自定义注册序列化程序,因为它会引发错误

Exception in thread django-main-thread:
Traceback (most recent call last):
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/db/models/options.py",line 581,in get_field
    return self.fields_map[field_name]
KeyError: 'username'

During handling of the above exception,another exception occurred:

Traceback (most recent call last):
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/threading.py",line 926,in _bootstrap_inner
    self.run()
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/threading.py",line 870,in run
    self._target(*self._args,**self._kwargs)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/utils/autoreload.py",line 53,in wrapper
    fn(*args,**kwargs)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/core/management/commands/runserver.py",line 117,in inner_run
    self.check(display_num_errors=True)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/core/management/base.py",line 395,in check
    include_deployment_checks=include_deployment_checks,File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/core/management/base.py",line 382,in _run_checks
    return checks.run_checks(**kwargs)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/core/checks/registry.py",line 72,in run_checks
    new_errors = check(app_configs=app_configs)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/core/checks/urls.py",line 13,in check_url_config
    return check_resolver(resolver)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/core/checks/urls.py",line 23,in check_resolver
    return check_method()
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/urls/resolvers.py",line 407,in check
    for pattern in self.url_patterns:
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/utils/functional.py",line 48,in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/urls/resolvers.py",line 588,in url_patterns
    patterns = getattr(self.URLconf_module,"urlpatterns",self.URLconf_module)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/utils/functional.py",in URLconf_module
    return import_module(self.URLconf_name)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/importlib/__init__.py",line 127,in import_module
    return _bootstrap._gcd_import(name[level:],package,level)
  File "<frozen importlib._bootstrap>",line 1006,in _gcd_import
  File "<frozen importlib._bootstrap>",line 983,in _find_and_load
  File "<frozen importlib._bootstrap>",line 967,in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>",line 677,in _load_unlocked
  File "<frozen importlib._bootstrap_external>",line 728,in exec_module
  File "<frozen importlib._bootstrap>",line 219,in _call_with_frames_removed
  File "/Users/torsten/journal/journal/urls.py",line 26,in <module>
    url(r'^rest-auth/registration/',include('rest_auth.registration.urls'))
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/urls/conf.py",line 34,in include
    URLconf_module = import_module(URLconf_module)
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/importlib/__init__.py",in _call_with_frames_removed
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/rest_auth/registration/urls.py",line 4,in <module>
    from .views import RegisterView,VerifyEmailView
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/rest_auth/registration/views.py",in <module>
    from rest_auth.registration.serializers import (VerifyEmailSerializer,File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/rest_auth/registration/serializers.py",line 166,in <module>
    class RegisterSerializer(serializers.Serializer):
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/rest_auth/registration/serializers.py",line 168,in RegisterSerializer
    max_length=get_username_max_length(),File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/allauth/utils.py",line 63,in get_username_max_length
    max_length = User._Meta.get_field(USER_MODEL_USERNAME_FIELD).max_length
  File "/Users/torsten/opt/anaconda3/envs/journal/lib/python3.7/site-packages/django/db/models/options.py",line 583,in get_field
    raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name,field_name))
django.core.exceptions.FieldDoesNotExist: User has no field named 'username'

有趣的是,如果我只删除/site-packages/dj_rest_auth/registration/serializers.py中的行

username = serializers.CharField(
    max_length=get_username_max_length(),min_length=allauth_settings.USERNAME_MIN_LENGTH,required=allauth_settings.USERNAME_required
)

注册可以完美运行,并且可以选择我的自定义序列化程序,让我可以毫无问题地注册新用户。但是像这样直接篡改程序包文件似乎确实是一个非常棘手的解决方案。

有人知道如何在不编辑dj_rest_auth软件包的源代码的情况下摆脱上面的错误吗?

编辑:这是我的自定义寄存器序列化器的代码

class CustomregisterSerializer(serializers.Serializer):
    email = serializers.EmailField(required=True)
    password1 = serializers.CharField(write_only=True)
    password2 = serializers.CharField(write_only=True)

    def get_cleaned_data(self):
        return {
            "password": self.validated_data.get("password1",""),"email": self.validated_data.get("email",}

    def save(self,request):
        self.cleaned_data = self.get_cleaned_data()
        user = User(**self.cleaned_data)
        user.save()
        return user

解决方法

所以我想知道为什么导入其他4个序列化程序会触发该错误,然后发现该错误:

class RegisterSerializer(serializers.Serializer):
    username = serializers.CharField(
        max_length=get_username_max_length(),min_length=allauth_settings.USERNAME_MIN_LENGTH,required=allauth_settings.USERNAME_REQUIRED
    )

函数get_username_max_length()在声明时被调用,该函数调用allauth实用程序方法,该方法导入用户模型并从字段中获取最大长度。

您的解决方法是在设置中将ACCOUNT_USER_MODEL_USERNAME_FIELD设置为None,以便它仅返回0,而无需尝试从用户模型中获取用户名字段。