在 Django 中创建自定义用户 Class
Creating Custom User Class in Django
我已经阅读并重新阅读了有关此问题的其他问题,但我仍然无法创建自定义 Django 用户模型。我不断收到错误消息:Manager isn't available; 'auth.User' has been swapped for 'Users.User'
.
如果错误不清楚,我创建了一个 Users
应用程序,其中 models.py
文件定义了一个自定义用户 class User
.
这是我项目中的相关文件,UserTest
:
- 正在注册应用程序,指定自定义用户模型:
UserTest> UserTest> settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'Users'
]
AUTH_USER_MODEL = 'Users.User'
- 通过我的
User
模型扩展默认 Django 用户 class 并将其连接到 Profile
模型(与问题不严格相关,但方法的基本方面。)
UserTest > 用户 > models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
email = models.CharField(max_length=128, blank=False, unique=True, verbose_name='Email', name='email')
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
- 正在我的
Users
应用的 admin.py 中注册新的 User
模型(不确定这是否是测试快速前端功能所必需的?)
UserTest > 用户 > admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)
我已经创建了一些基本表单和一个视图,以允许前端提交相关用户和配置文件数据。鉴于错误,我认为它们不相关,但如果有人认为它们相关,我可以将它们包括在内。同样,错误如下:
Manager isn't available; 'auth.User' has been swapped for 'Users.User'
我最初使用 AbstractBaseUser
class 创建了自定义 User
模型,文档描述了自定义管理器 class 还必须 被创建。我在使用这种方法时遇到了同样的错误,并且没有读到使用这种方法时需要相同的定制,依赖于 AbstractUser
在我的 UserTest > Users > forms.py 文件中,我尝试通过以下两种方式访问我的 Users.models.User
模型:
- 直接导入:
from .models import User
- 通过这样使用 Django 的
get_user_model()
函数:
from django.contrib.auth import get_user_model
User = get_user_model()
第二种方法似乎已经为许多其他人解决了这个问题,例如问题 HERE 但对我没有帮助(除非我遗漏了什么)。
错误的完整回溯在这里:
Internal Server Error: /test-form/
Traceback (most recent call last):
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\...\Desktop\UserTest\Users\views.py", line 19, in NewUserRegistration
print("USERFORM:", user_form, type(user_form), dir(user_form))
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\utils\html.py", line 397, in <lambda>
klass.__str__ = lambda self: mark_safe(klass_str(self))
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 142, in __str__
return self.as_table()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 284, in as_table
errors_on_separate_row=False,
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 202, in _html_output
top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 313, in non_field_errors
return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield'))
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 180, in errors
self.full_clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 383, in full_clean
self._post_clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\contrib\auth\forms.py", line 107, in _post_clean
super()._post_clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\models.py", line 403, in _post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\db\models\base.py", line 1137, in full_clean
self.clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\contrib\auth\models.py", line 338, in clean
self.email = self.__class__.objects.normalize_email(self.email)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\db\models\manager.py", line 188, in __get__
cls._meta.swapped,
AttributeError: Manager isn't available; 'auth.User' has been swapped for 'Users.User'
[26/Oct/2018 09:47:02] "POST /test-form/ HTTP/1.1" 500 118088
感谢任何帮助。通常,如果我能够在没有 "aha" 的情况下在 SO 上键入整个 post,我就知道我被搞砸了。
更新 1:添加 forms.py
和 views.py
在我的UserTest > Users
应用程序中,views.py
和forms.py
如下:
UserTest > 用户 > forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.core.exceptions import ValidationError
from django.contrib.auth import get_user_model
User = get_user_model()
class NewUser(UserCreationForm):
email = forms.EmailField(max_length=96)
password = forms.PasswordInput()
username = forms.CharField(max_length=18)
def clean_email(self):
email = self.cleaned_data['email'].lower()
r = User.objects.filter(email=email)
if r.count():
raise ValidationError("Email already exists")
return email
def save(self, commit=True):
user = User.objects.create_user(
self.cleaned_data['email'],
self.cleaned_data['password'],
self.cleaned_data['username']
)
return user
注意:我在这里尝试了 get_user_model()
方法以及从 Users.models
导入我的自定义 User
class,但都没有解决错误。
UserTest > 用户 > views.py
from django.shortcuts import render
from django.contrib import messages
from .forms import NewUser
def NewUserRegistration(request):
if request.method == 'POST':
user_form = NewUser(request.POST)
if user_form.is_valid():
user_form.save()
messages.success(request, 'Account Created Successfully!')
else:
user_form = NewUser()
return render(request, 'Users/test-form.html', {'user_form': user_form})
当您使用自定义 user model
时,它需要定义它的 objects
即它的 manager
,其中包含它的各种方法,如 create_user
或 create_superuser
。
您可以使用 BaseUserManager
在您的自定义管理器中继承并在您的 User
模型中定义它。
它可能像 -
class UserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
date_of_birth=date_of_birth,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractUser):
email = models.CharField(max_length=128, blank=False, unique=True, verbose_name='Email', name='email')
objects = UserManager()
这是一个简单的示例,您可以根据需要使用UserManager
。
重新开始参考文档以获得更清晰的理解 - https://docs.djangoproject.com/en/2.1/topics/auth/customizing/
由于 the documentation explains,诸如 UserCreationForm 之类的表单与 User 相关联,需要重写或扩展以使用自定义用户模型。
因此,如图所示,您需要覆盖内部 Meta class 以指向您的模型:
class NewUser(UserCreationForm):
...
class Meta(UserCreationForm.Meta):
model = get_user_model()
我已经阅读并重新阅读了有关此问题的其他问题,但我仍然无法创建自定义 Django 用户模型。我不断收到错误消息:Manager isn't available; 'auth.User' has been swapped for 'Users.User'
.
如果错误不清楚,我创建了一个 Users
应用程序,其中 models.py
文件定义了一个自定义用户 class User
.
这是我项目中的相关文件,UserTest
:
- 正在注册应用程序,指定自定义用户模型:
UserTest> UserTest> settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'Users'
]
AUTH_USER_MODEL = 'Users.User'
- 通过我的
User
模型扩展默认 Django 用户 class 并将其连接到Profile
模型(与问题不严格相关,但方法的基本方面。)
UserTest > 用户 > models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
email = models.CharField(max_length=128, blank=False, unique=True, verbose_name='Email', name='email')
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
...
- 正在我的
Users
应用的 admin.py 中注册新的User
模型(不确定这是否是测试快速前端功能所必需的?)
UserTest > 用户 > admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
admin.site.register(User, UserAdmin)
我已经创建了一些基本表单和一个视图,以允许前端提交相关用户和配置文件数据。鉴于错误,我认为它们不相关,但如果有人认为它们相关,我可以将它们包括在内。同样,错误如下:
Manager isn't available; 'auth.User' has been swapped for 'Users.User'
我最初使用 AbstractBaseUser
class 创建了自定义 User
模型,文档描述了自定义管理器 class 还必须 被创建。我在使用这种方法时遇到了同样的错误,并且没有读到使用这种方法时需要相同的定制,依赖于 AbstractUser
在我的 UserTest > Users > forms.py 文件中,我尝试通过以下两种方式访问我的 Users.models.User
模型:
- 直接导入:
from .models import User
- 通过这样使用 Django 的
get_user_model()
函数:
from django.contrib.auth import get_user_model
User = get_user_model()
第二种方法似乎已经为许多其他人解决了这个问题,例如问题 HERE 但对我没有帮助(除非我遗漏了什么)。
错误的完整回溯在这里:
Internal Server Error: /test-form/
Traceback (most recent call last):
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\core\handlers\exception.py", line 34, in inner
response = get_response(request)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\core\handlers\base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\core\handlers\base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "C:\Users\...\Desktop\UserTest\Users\views.py", line 19, in NewUserRegistration
print("USERFORM:", user_form, type(user_form), dir(user_form))
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\utils\html.py", line 397, in <lambda>
klass.__str__ = lambda self: mark_safe(klass_str(self))
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 142, in __str__
return self.as_table()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 284, in as_table
errors_on_separate_row=False,
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 202, in _html_output
top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 313, in non_field_errors
return self.errors.get(NON_FIELD_ERRORS, self.error_class(error_class='nonfield'))
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 180, in errors
self.full_clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\forms.py", line 383, in full_clean
self._post_clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\contrib\auth\forms.py", line 107, in _post_clean
super()._post_clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\forms\models.py", line 403, in _post_clean
self.instance.full_clean(exclude=exclude, validate_unique=False)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\db\models\base.py", line 1137, in full_clean
self.clean()
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\contrib\auth\models.py", line 338, in clean
self.email = self.__class__.objects.normalize_email(self.email)
File "C:\Users\...\Desktop\UserTest\venv\lib\site-packages\django\db\models\manager.py", line 188, in __get__
cls._meta.swapped,
AttributeError: Manager isn't available; 'auth.User' has been swapped for 'Users.User'
[26/Oct/2018 09:47:02] "POST /test-form/ HTTP/1.1" 500 118088
感谢任何帮助。通常,如果我能够在没有 "aha" 的情况下在 SO 上键入整个 post,我就知道我被搞砸了。
更新 1:添加 forms.py
和 views.py
在我的UserTest > Users
应用程序中,views.py
和forms.py
如下:
UserTest > 用户 > forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.core.exceptions import ValidationError
from django.contrib.auth import get_user_model
User = get_user_model()
class NewUser(UserCreationForm):
email = forms.EmailField(max_length=96)
password = forms.PasswordInput()
username = forms.CharField(max_length=18)
def clean_email(self):
email = self.cleaned_data['email'].lower()
r = User.objects.filter(email=email)
if r.count():
raise ValidationError("Email already exists")
return email
def save(self, commit=True):
user = User.objects.create_user(
self.cleaned_data['email'],
self.cleaned_data['password'],
self.cleaned_data['username']
)
return user
注意:我在这里尝试了 get_user_model()
方法以及从 Users.models
导入我的自定义 User
class,但都没有解决错误。
UserTest > 用户 > views.py
from django.shortcuts import render
from django.contrib import messages
from .forms import NewUser
def NewUserRegistration(request):
if request.method == 'POST':
user_form = NewUser(request.POST)
if user_form.is_valid():
user_form.save()
messages.success(request, 'Account Created Successfully!')
else:
user_form = NewUser()
return render(request, 'Users/test-form.html', {'user_form': user_form})
当您使用自定义 user model
时,它需要定义它的 objects
即它的 manager
,其中包含它的各种方法,如 create_user
或 create_superuser
。
您可以使用 BaseUserManager
在您的自定义管理器中继承并在您的 User
模型中定义它。
它可能像 -
class UserManager(BaseUserManager):
def create_user(self, email, date_of_birth, password=None):
"""
Creates and saves a User with the given email, date of
birth and password.
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=self.normalize_email(email),
date_of_birth=date_of_birth,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, date_of_birth, password):
"""
Creates and saves a superuser with the given email, date of
birth and password.
"""
user = self.create_user(
email,
password=password,
date_of_birth=date_of_birth,
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractUser):
email = models.CharField(max_length=128, blank=False, unique=True, verbose_name='Email', name='email')
objects = UserManager()
这是一个简单的示例,您可以根据需要使用UserManager
。
重新开始参考文档以获得更清晰的理解 - https://docs.djangoproject.com/en/2.1/topics/auth/customizing/
由于 the documentation explains,诸如 UserCreationForm 之类的表单与 User 相关联,需要重写或扩展以使用自定义用户模型。
因此,如图所示,您需要覆盖内部 Meta class 以指向您的模型:
class NewUser(UserCreationForm):
...
class Meta(UserCreationForm.Meta):
model = get_user_model()