django - Django 尝试保存 AbstractUser 模型时出错
问题描述
我想将此 AbstractUser 保存在我的模型中。
#app_name members
#models.py
class User(AbstractUser):
is_student = models.BooleanField(default=False)
is_teacher = models.BooleanField(default=False)
设置.py
INSTALLED_APPS = [
#deful django app...
#others app....
'members',
]
AUTH_USER_MODEL = 'members.User'
makemigrations
在出现此错误之前尝试保存时
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:
ERRORS:
auth.User.groups: (fields.E304) Reverse accessor for 'auth.User.groups' clashes with reverse accessor for 'members.User.groups'.
HINT: Add or change a related_name argument to the definition for 'auth.User.groups' or 'members.User.groups'.
auth.User.user_permissions: (fields.E304) Reverse accessor for 'auth.User.user_permissions' clashes with reverse accessor for 'members.User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'auth.User.user_permissions' or 'members.User.user_permissions'.
members.User.groups: (fields.E304) Reverse accessor for 'members.User.groups' clashes with reverse accessor for 'auth.User.groups'.
HINT: Add or change a related_name argument to the definition for 'members.User.groups' or 'auth.User.groups'.
members.User.user_permissions: (fields.E304) Reverse accessor for 'members.User.user_permissions' clashes with reverse accessor for 'auth.User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'members.User.user_permissions' or 'auth.User.user_permissions
为什么会出现这个错误?如何解决?
我也试过这个AUTH_USER_MODEL = 'myAppName.myClassName'
并得到这个错误
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:
ERRORS:
blog.Blog.author: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
blog.BlogComment.user: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
blog.GlobalNotifications.user: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
notifications.Notifications.receiver: (fields.E301) Field defines a
relation with the model 'auth.User', which has been swapped out.
HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
notifications.Notifications.sender: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.
解决方案
django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:
ERRORS:
auth.User.groups: (fields.E304) Reverse accessor for 'auth.User.groups' clashes with reverse accessor for 'members.User.groups'.
HINT: Add or change a related_name argument to the definition for 'auth.User.groups' or 'members.User.groups'.
auth.User.user_permissions: (fields.E304) Reverse accessor for 'auth.User.user_permissions' clashes with reverse accessor for 'members.User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'auth.User.user_permissions' or 'members.User.user_permissions'.
members.User.groups: (fields.E304) Reverse accessor for 'members.User.groups' clashes with reverse accessor for 'auth.User.groups'.
HINT: Add or change a related_name argument to the definition for 'members.User.groups' or 'auth.User.groups'.
members.User.user_permissions: (fields.E304) Reverse accessor for 'members.User.user_permissions' clashes with reverse accessor for 'auth.User.user_permissions'.
HINT: Add or change a related_name argument to the definition for 'members.User.user_permissions' or 'auth.User.user_permissions
基本上这个错误是说你需要有 unqiue related_name 作为相关名称,以确保字段之间没有冲突。它找不到 settings.AUTH_USER_MODEL 因为你没有运行 makemigrations
如果你想用 is_student, is_teacher 创建自定义用户,你可以按照下面的代码,因为这就是我喜欢创建自定义用户的方式
您需要先运行 makemigrations 和 migrate 才能对其进行测试!或者您可以创建单独的应用程序以查看此自定义用户是否满足您的需求。
在 utils.py
from django.db import models
import random
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class IntegerRangeField(models.IntegerField):
"""
This model handels :
- Creating custom IntegerField with min/ max value.
- Used in Users class, employee_number.
- Gives each employee exactly 4 digits integer.
- Can be edited in future if company grows in size.
...
Attributes:
----------
min_value :
minimum number.
max_value:
maximum number.
Methods:
formfield(self, **kwargs):
- create new defaults for IntegerField then update them.
"""
def __init__(self, verbose_name=None, name=None, min_value=None, max_value=None, **kwargs):
self.min_value, self.max_value = min_value, max_value
models.IntegerField.__init__(self, verbose_name, name, **kwargs)
def formfield(self, **kwargs):
defaults = {'min_value': self.min_value, 'max_value':self.max_value}
defaults.update(kwargs)
return super(IntegerRangeField, self).formfield(**defaults)
# generate random number from 1000, 9000
def create_new_employee_number():
return random.randint(1000,9999)
class CustomUserManager(BaseUserManager):
"""
Custom user model manager where username is unique identifiers
able to add more fields to Django basic User model.
"""
def create_student(self, username, password, **extra_fields):
"""
Create and save a User with the given email and password.
"""
if not username:
raise ValueError(_('The username must be set'))
user = self.model(username=username, **extra_fields)
user.set_password(password)
user.save()
return user
def create_superuser(self, username, password, **extra_fields):
"""
Create and save a SuperUser with the given email and password.
"""
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
extra_fields.setdefault('is_active', True)
extra_fields.setdefault('is_student', False)
extra_fields.setdefault('is_teacher', False)
if extra_fields.get('is_staff') is not True:
raise ValueError(_('Superuser must have is_staff=True.'))
if extra_fields.get('is_superuser') is not True:
raise ValueError(_('Superuser must have is_superuser=True.'))
return self.create_user(username, password, **extra_fields)
def create_teacher(self, username, first_name, last_name, password=None):
if not username:
raise ValueError("User must have an email")
if not password:
raise ValueError("User must have a password")
if not first_name:
raise ValueError("User must have a first name")
if not last_name:
raise ValueError("User must have a last name")
user = self.model(
email=self.normalize_email(username)
)
user.first_name = first_name
user.last_name = last_name
user.set_password(password) # change password to hash
user.is_admin = False
user.is_staff = True
user.save(using=self._db)
return user
def create_staffuser(self, username, first_name, last_name, password=None):
if not username:
raise ValueError("User must have an email")
if not password:
raise ValueError("User must have a password")
if not first_name:
raise ValueError("User must have a first name")
if not last_name:
raise ValueError("User must have a last name")
user = self.model(
email=self.normalize_email(username)
)
user.first_name = first_name
user.last_name = last_name
user.set_password(password) # change password to hash
user.is_admin = False
user.is_staff = False
user.is_teacher=True
user.save(using=self._db)
return user
现在在models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
from django.db.models.signals import post_save, pre_save
from django.utils.translation import ugettext_lazy as _
from django.core.exceptions import ValidationError
import datetime
from .utils import (
IntegerRangeField,
CustomUserManager,
create_new_employee_number
)
ROLES_CHOICES = (
('ST', 'Student'),
('TC', 'Teacher')
)
class User(AbstractUser):
"""
This model handels :
- follows django docs on how to customizing user mode.
- https://docs.djangoproject.com/en/3.2/topics/auth/customizing/
- Creating new users into the database.
- aumatically genearte JWT from the home/urls.py "rest_auth.registration.urls"
...
Attributes:
----------
username :
unique string field, max_length is 50
name:
user first and last name.
role:
user role two options(ST: Student, TC: Teacher)
id:
unique randomly generated integer, editable by admin.
uses custom field, more details about IntegerRangeField in utils.py
Methods:
__str__
return a string repr of the user, username.
"""
username = models.CharField(unique=True, max_length=50)
name = models.CharField(max_length=50, blank=True, default="Employee")
role = models.CharField(
max_length=50, choices=ROLES_CHOICES,
blank=False, null=False, default="ST",
error_messages = {'invalid': "Role is two choices ADMIN or EM"}
)
id= IntegerRangeField(
min_value=1000, max_value=9999, editable=True, blank=True,
unique=True, default=create_new_employee_number,
error_messages={'invalid': "employee_number is unique integer 1000-9999"}
)
objects = CustomUserManager()
def __str__(self):
return self.username
推荐阅读
- react-native - 如何使用 ui kitten 卸载非活动屏幕
- mysql - 一个有说服力的查询的多个总计
- java - 这是与我的文件(application.properties)中的 mongodb 配置有关的问题吗?
- javascript - JS:如何获取err.code?在我的代码中它总是未定义
- c# - Typescript API 打开 PDF 文件
- google-data-studio - 如何根据非聚合数据在 Google Data Studio 中的框上创建动态悬停
- r - 在 ggplot2 中使用多列作为 R 的 x 轴
- python - 首次启动时 Catalyst SupervisedRunner 断言错误
- c# - httpRuntime targetFramework 和安装的实际框架
- django - 如何使用 django inlineformset_factory 允许用户在基于函数的视图中创建课程