Django - Как установить ForeignKey в модель, которая сама имеет отношение один-к-одному с User?
Вот мой класс:
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. У меня возникают трудности при попытке сослаться на CredsKeychain из CredKey. Я могу напрямую связать пользователя через:
keychain = models.ForeignKey(User, on_delete=models.CASCADE)
Но это не то, что мне нужно. На самом деле мне нужно иметь отношение ForeignKey к CredsKeychain, которое имеет отношение один-к-одному с текущим пользователем (который отправляет страницу в Django admin).
Когда я пытаюсь перенести эту модель (в ее текущем состоянии), я получаю ошибку:
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\0001_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
Если вы хотите добавить новые поля в ваши модели, убедитесь, что у вас нет ранее добавленных записей в БД. Если у вас есть записи, вы должны вывести некоторые значения по умолчанию в поле модели. Потому что, когда вы пытаетесь перенести новые поля без значения по умолчанию, что должна делать БД? Как она должна заполнить предыдущие записи? Поэтому есть 2 способа исправить это, как сказано:
- Предоставить одноразовое значение по умолчанию (будет установлено для всех существующих строк с нулевым значением для этого столбца)
- Выйти и вручную определить значение по умолчанию в models.py.
поэтому вы можете выбрать вариант 1 и написать команду на python для заполнения предыдущих записей или выбрать вариант 2 и определить значение по умолчанию в поле модели вручную