Django-将Auth用户名更改为Autofield会破坏代码 [英] Django - Changing Auth username to Autofield breaks the code

查看:43
本文介绍了Django-将Auth用户名更改为Autofield会破坏代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个需要将用户名字段更改为 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆