在Django中有一个继承AbstractUser
的自定义用户模型。
模型有username = None
,下面是模型:
class User(AbstractUser):
username = None
email = models.EmailField(_("Email address"), unique=True)
USERNAME_FIELD = "email"
我想删除username = None
,这样我们也可以保存用户名。
但问题是我们在数据库中有不同的用户。
当我删除username = None
并尝试迁移时,我得到了提示符:
不可能在不指定默认值的情况下向用户添加非空字段“用户名”。这是因为数据库需要一些东西来填充现有的行。请选择一个修复程序:
中手动定义默认值)。
我不想覆盖username
类的AbstractUser
字段。
AbstractUser > username
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
的值。
如何提供默认值?
发布于 2022-10-20 07:48:21
您可以使用自定义迁移。在创建迁移时,提供一个默认值,然后使用以下内容编辑生成的迁移:
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
,从而使字段成为必需的字段。
发布于 2022-10-20 07:19:43
您可以像这样使用pre_save
信号:
# 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循环:
$ python manage.py shell
>> from users.models import User
>> for user in User.objects.all():
... user.username = user.email
... user.save()
发布于 2022-10-20 06:56:54
您可以对旧值使用迁移,并在序列化程序中为新条目编写用户名的setter。
https://stackoverflow.com/questions/74135368
复制相似问题