Django - 如何将 ForeignKey 设置为本身与用户具有一对一关系的模型?
Django - How to set ForeignKey to a model that itself has a one-to-one relationship to User?
这是我的 class:
from django.db import models
from django.contrib.auth.models import User
class CredsKeychain(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self) -> str:
return f"{self.user.username}'s credentials"
class CredKey(models.Model):
keychain = models.ForeignKey(CredsKeychain, on_delete=models.CASCADE)
tag = models.CharField(max_length=100)
username = models.CharField(max_length=100)
enc_password = models.CharField(max_length=100)
last_used_successfully = models.DateTimeField(default=None)
def __str__(self) -> str:
return f"{self.keychain.user.username}'s credentials for {self.tag} [{self.username}]"
我正在尝试建立关系,以便每个用户都有一个 CredsKeychain
,其中包含多个 CredKey
对象。我很难尝试从 CredKey 引用 CredsKeychain。我可以直接 link 用户,通过:
keychain = models.ForeignKey(User, on_delete=models.CASCADE)
但这不是我需要的。我实际上需要与与当前用户(在 Django 管理中提交页面的用户)具有一对一关系的 CredsKeychain 建立外键关系。
当我尝试迁移此模型(处于当前状态)时,出现错误:
It is impossible to add a non-nullable field 'keychain' to credkey without specifying a default. This is because the database needs something to populate existing rows.
Please select a fix:
- Provide a one-off default now (will be set on all existing rows with a null value for this column)
- Quit and manually define a default value in models.py.
如何引用 user.credskeychain
?
更新:我已经有一个信号设置,这样每次创建用户时,它都会自动为该用户创建一个 CredsKeychain
。
@receiver(post_save, sender=User)
def setup_keychain(sender, instance:User, created, **kwargs):
if created:
CredsKeychain.objects.create(user = instance)
更新 2:一旦我删除了数据库并删除了旧的迁移(删除了数据库),模型就可以正常工作了。现在我重新开始,它迁移得很好。那么之前的问题是什么?!
(env) PS C:\Users\somsinha\scripts\djpu-keystore> python manage.py makemigrations
Migrations for 'keystore':
keystore\migrations[=13=]01_initial.py
- Create model CredsKeychain
- Create model CredKey
(env) PS C:\Users\somsinha\scripts\djpu-keystore> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, keystore, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying keystore.0001_initial... OK
Applying sessions.0001_initial... OK
如果您想向模型中添加任何新字段,请确保数据库中没有任何先前添加的记录。如果你有任何记录,你应该在模型字段中去掉一些默认值。因为当您尝试迁移没有任何默认值的新字段时,DB 应该做什么?以前的记录应该怎么填?所以有 2 种方法可以修复它:
- Provide a one-off default now (will be set on all existing rows with a null value for this column)
- Quit and manually define a default value in models.py.
所以你可以 select 选项 1 并编写 python 命令来填充以前的记录或 select 选项 2 并在模型字段中手动定义默认值
这是我的 class:
from django.db import models
from django.contrib.auth.models import User
class CredsKeychain(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self) -> str:
return f"{self.user.username}'s credentials"
class CredKey(models.Model):
keychain = models.ForeignKey(CredsKeychain, on_delete=models.CASCADE)
tag = models.CharField(max_length=100)
username = models.CharField(max_length=100)
enc_password = models.CharField(max_length=100)
last_used_successfully = models.DateTimeField(default=None)
def __str__(self) -> str:
return f"{self.keychain.user.username}'s credentials for {self.tag} [{self.username}]"
我正在尝试建立关系,以便每个用户都有一个 CredsKeychain
,其中包含多个 CredKey
对象。我很难尝试从 CredKey 引用 CredsKeychain。我可以直接 link 用户,通过:
keychain = models.ForeignKey(User, on_delete=models.CASCADE)
但这不是我需要的。我实际上需要与与当前用户(在 Django 管理中提交页面的用户)具有一对一关系的 CredsKeychain 建立外键关系。
当我尝试迁移此模型(处于当前状态)时,出现错误:
It is impossible to add a non-nullable field 'keychain' to credkey without specifying a default. This is because the database needs something to populate existing rows. Please select a fix:
- Provide a one-off default now (will be set on all existing rows with a null value for this column)
- Quit and manually define a default value in models.py.
如何引用 user.credskeychain
?
更新:我已经有一个信号设置,这样每次创建用户时,它都会自动为该用户创建一个 CredsKeychain
。
@receiver(post_save, sender=User)
def setup_keychain(sender, instance:User, created, **kwargs):
if created:
CredsKeychain.objects.create(user = instance)
更新 2:一旦我删除了数据库并删除了旧的迁移(删除了数据库),模型就可以正常工作了。现在我重新开始,它迁移得很好。那么之前的问题是什么?!
(env) PS C:\Users\somsinha\scripts\djpu-keystore> python manage.py makemigrations
Migrations for 'keystore':
keystore\migrations[=13=]01_initial.py
- Create model CredsKeychain
- Create model CredKey
(env) PS C:\Users\somsinha\scripts\djpu-keystore> python manage.py migrate
Operations to perform:
Apply all migrations: admin, auth, contenttypes, keystore, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying auth.0012_alter_user_first_name_max_length... OK
Applying keystore.0001_initial... OK
Applying sessions.0001_initial... OK
如果您想向模型中添加任何新字段,请确保数据库中没有任何先前添加的记录。如果你有任何记录,你应该在模型字段中去掉一些默认值。因为当您尝试迁移没有任何默认值的新字段时,DB 应该做什么?以前的记录应该怎么填?所以有 2 种方法可以修复它:
- Provide a one-off default now (will be set on all existing rows with a null value for this column)
- Quit and manually define a default value in models.py.
所以你可以 select 选项 1 并编写 python 命令来填充以前的记录或 select 选项 2 并在模型字段中手动定义默认值