问题描述
我有一个自定义用户模型,该模型使用电子邮件进行登录,并且没有用户名字段。我正在尝试使用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,而无需尝试从用户模型中获取用户名字段。