首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Django:为具有unique=True的新模型字段设置默认值

Django:为具有unique=True的新模型字段设置默认值
EN

Stack Overflow用户
提问于 2022-10-20 06:34:44
回答 3查看 77关注 0票数 1

在Django中有一个继承AbstractUser的自定义用户模型。

模型有username = None,下面是模型:

代码语言:javascript
运行
复制
class User(AbstractUser):
    username = None
    email = models.EmailField(_("Email address"), unique=True)

    USERNAME_FIELD = "email"

我想删除username = None,这样我们也可以保存用户名。

但问题是我们在数据库中有不同的用户。

当我删除username = None并尝试迁移时,我得到了提示符:

不可能在不指定默认值的情况下向用户添加非空字段“用户名”。这是因为数据库需要一些东西来填充现有的行。请选择一个修复程序:

  1. Provide (现在是一次性默认的)(将在所有现有行上设置此column)
  2. Quit的空值,并在models.py.

中手动定义默认值)。

我不想覆盖username类的AbstractUser字段。

AbstractUser > username

代码语言:javascript
运行
复制
username_validator = UnicodeUsernameValidator()

    username = models.CharField(
        _("username"),
        max_length=150,
        unique=True,
        help_text=_(
            "Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only."
        ),
        validators=[username_validator],
        error_messages={
            "unique": _("A user with that username already exists."),
        },
    )

如果没有提供不同的值,我希望username接受email的值。

如何提供默认值?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-10-20 07:48:21

您可以使用自定义迁移。在创建迁移时,提供一个默认值,然后使用以下内容编辑生成的迁移:

代码语言:javascript
运行
复制
import django.contrib.auth.models
from django.db import migrations, models
import users.models


def forwards_func(apps, schema_editor):
    User = apps.get_model("users", "User")
    User.objects.update(username=models.F("email"))


def reverse_func(apps, schema_editor):
    pass


class Migration(migrations.Migration):

    dependencies = [
        ('users', '0001_initial'),
    ]

    operations = [
        migrations.AlterModelManagers(
            name='user',
            managers=[
                ('manager', users.models.UserManager()),
                ('objects', django.contrib.auth.models.UserManager()),
            ],
        ),
        migrations.AddField(
            model_name='user',
            name='username',
            field=models.EmailField(max_length=254, unique=True, null=True),
            preserve_default=False,
        ),
        migrations.RunPython(forwards_func, reverse_func),
        migrations.AlterField(
            model_name='user',
            name='username',
            field=models.EmailField(max_length=254, unique=True),
        ),
    ]

以下是对这些变化的解释:

  • 首先,将null=True添加到新的username字段,使该列为空。
  • 通过RunPython操作更新现有用户的用户名列。在forward_func中,我们为username使用email列的值。反函数可以是空的,因为该列将被移除。现在您可以通过AlterField.

null设置为默认值False,从而使字段成为必需的字段。

票数 3
EN

Stack Overflow用户

发布于 2022-10-20 07:19:43

您可以像这样使用pre_save信号:

代码语言:javascript
运行
复制
# signals.py

from django.db.models.signals import pre_save
from django.dispatch import receiver

@receiver(pre_save, sender=User)
def fill_username(sender, instance, *args, **kwargs):
    if not instance.username:
        instance.username = instance.email

# apps.py

class UserConfig(AppConfig):
    ...

    def ready(self):
        import users.signals

通过这种方式,它将始终检查用户名是否被输入。如果它是空的,它将从电子邮件中复制值。

对于现有用户,您可能需要手动调用save()或在shell中调用For循环:

代码语言:javascript
运行
复制
$ python manage.py shell

>> from users.models import User
>> for user in User.objects.all():
...    user.username = user.email
...    user.save()
票数 1
EN

Stack Overflow用户

发布于 2022-10-20 06:56:54

您可以对旧值使用迁移,并在序列化程序中为新条目编写用户名的setter。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74135368

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档