Django-将Auth用户名更改为Autofield会破坏代码 [英] Django - Changing Auth username to Autofield breaks the code
问题描述
我有一个需要将用户名字段更改为 Autofield
的应用程序.
I've an application where I need to change username field to Autofield
.
用例-我正在构建一个应用程序,在该应用程序中创建用户时,用户名应类似于银行应用程序中的CustomerID(整数).
Use-case - I'am building an application where when the users will be created, usernames should be like CustomerID(integers) in banking applications.
有两种方法可以做到:-
There are 2 ways of doing it:-
1)拥有 id
(PK),它是其默认实现.复制对象的 id
,并将其分配给username列,以允许用户通过id登录.权衡
1) Have an id
(PK), the default implementation of it. Copy the id
, of the object and assign it to the username column, to allow users to sign-in via the id. Trade-offs
- 两个重复的列.
- 我怎么称呼 create_user 功能,因为它需要用户名.
- Two duplicate columns.
- How would I call create_user function as it requires username.
2)允许通过ID登录,更新AuthBackend并也允许通过ID登录.权衡
2) Allow login via the IDs, update AuthBackend and allow login via the IDs too. TradeOff
- 用户名的值是什么.我可以将其保存为电子邮件吗?
- 不确定,是否允许通过ID登录是个好主意.
Pheww,足够多的讨论.现在是实现(问题)部分.:-
这是我的模特.
class User(AbstractUser):
username = models.BigAutoField(primary_key=True)
user_id = models.UUIDField(default=uuid.uuid4, unique=True,
editable=False)
一个模型不能具有多个 AutoField
,因此, username
是PK.
A model can't have more than one AutoField
, as a result, username
is PK.
我的迁移工作非常顺利.并创建了表.
I migrations worked perfectly well. And the table was created.
但是,当我使用创建用户
However, when I create a user using
User.objects.create_user(email=email, password=password) #expecting the username to be auto-generated.
说用户名是必填项.
我检查了 Django代码UserManager
函数 create_user
,并更新了参数 username = None
I checked Django code UserManager
function create_user
, and updated argument username=None
class CustomUserManager(UserManager):
use_in_migrations = True
def create_user(self, username=None, email=None, password=None,
**extra_fields):
return super(CustomUserManager, self).create_user(username=username,
email=email,
password=password,
extra_fields=extra_fields)
它仍然引发异常:-
In [4]: User.objects.create_user(email='ab@ab.com', password='abcd1234@')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-4-de9c49dd635d> in <module>()
----> 1 User.objects.create_user(email='ab@ab.com', password='abcd1234@')
/Users/praful/Desktop/code/seynse/authentication/app/modules/users/models.py in create_user(self, username, email, password, **extra_fields)
17 email=email,
18 password=password,
---> 19 extra_fields=extra_fields)
20
21
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/auth/models.py in create_user(self, username, email, password, **extra_fields)
157 extra_fields.setdefault('is_staff', False)
158 extra_fields.setdefault('is_superuser', False)
--> 159 return self._create_user(username, email, password, **extra_fields)
160
161 def create_superuser(self, username, email, password, **extra_fields):
/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/site-packages/django/contrib/auth/models.py in _create_user(self, username, email, password, **extra_fields)
146 """
147 if not username:
--> 148 raise ValueError('The given username must be set')
149 email = self.normalize_email(email)
150 username = self.model.normalize_username(username)
ValueError: The given username must be set
在这种情况下可以做什么?如何将用户名更改为 AutoField
.
What can be done in this case? How can I change username to AutoField
.
推荐答案
您必须为用户模型创建一个自定义管理器.它可以从 BaseManager
继承,但是不能从默认的 UserManager
:
You must create a custom manager for your user model. It can inherit from BaseManager
, but not from the default UserManager
:
class CustomUserManager(BaseUserManager):
use_in_migrations = True
def _create_user(self, email, password, **extra_fields):
"""
Create and save a user with the given email, and password.
"""
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
def create_user(self, email=None, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)
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(email, password, **extra_fields)
class User(AbstractUser):
username = models.BigAutoField(primary_key=True)
user_id = models.UUIDField(default=uuid.uuid4, unique=True,
editable=False)
objects = CustomUserManager()
def __str__(self):
return str(self.username)
请注意,我已经完全删除了 username
,因为没有必要为AutoField传递显式值.
Note that I've completely removed username
, as it doesn't make sense to pass an explicit value for an AutoField.
这篇关于Django-将Auth用户名更改为Autofield会破坏代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!