Django: ValueError: Невозможно присвоить "<User: x>": "UserRelatinoship.x" должен быть экземпляром "User".
Я пытаюсь автоматически создать отношения между двумя тестовыми пользователями в миграции в Django. Мой код миграции выглядит следующим образом:
# Generated manually
from django.db import migrations, transaction
from django.contrib.auth import get_user_model
def setup_test(apps, schema_editor):
User = get_user_model()
User.objects.create_superuser("admin", "admin@gm.org", "123")
x = User.objects.create_user(
username="x", email="a@gm.org", password="123"
)
y = User.objects.create_user(
username="y", email="b@gm.org", password="123"
)
UserRelatinoship = apps.get_model("myapp", "UserRelatinoship")
UserRelatinoship.objects.create(x=x, y=y, active=True)
class Migration(migrations.Migration):
dependencies = [
("myapp", "0001_initial"),
("myapp", "0002_manual"),
]
operations = [
migrations.RunPython(setup_test),
]
Код модели
from django.contrib.auth import get_user_model
User = get_user_model()
class UserRelationship(models.Model):
class Meta:
unique_together = (("x", "y"),)
x = models.ForeignKey(User, related_name="x", on_delete=models.CASCADE)
y = models.ForeignKey(User, related_name="y", on_delete=models.CASCADE)
active = models.BooleanField(default=True)
cancelled = models.BooleanField(default=False)
approved = models.BooleanField(default=False)
denied = models.BooleanField(default=False)
finalized = models.BooleanField(default=False)
def save(self, *args, **kwargs):
if self.approved:
self.active = True
if self.cancelled:
self.active = False
super().save(*args, **kwargs)
def __str__(self):
return f"{self.x}:{self.y}"
Пользователи создаются нормально, но затем, когда я пытаюсь создать отношения, я получаю ошибку ValueError: Cannot assign "<User: x>": "UserRelatinoship.x" must be a "User" instance.
. Кроме того, я могу создать отношения при запуске сервера и заполнении форм вручную, хотя код для этого выглядит примерно одинаково (за исключением того, что он использует request.user для одной части). Обратите внимание, что я изменил некоторые имена из моего первоначального кода. Любая помощь будет высоко оценена!
Редактирование:
Внутреннее условие django, которое не выполняется, это if value is not None and not isinstance(value, self.field.remote_field.model._meta.concrete_model):
Здесь у меня есть несколько отладочных строк
(Pdb) p value
<User: tutee>
(Pdb) p self.field.remote_field
<ManyToOneRel: tutor.tutortuteerelationship>
(Pdb) p self.field.remote_field.model
<class '__fake__.User'>
(Pdb) p self.field.remote_field.model._meta
<Options for User>
(Pdb) p self.field.remote_field.model._meta.concreate_model
*** AttributeError: 'Options' object has no attribute 'concreate_model'
(Pdb) p self.field.remote_field.model._meta.concrete_model
<class '__fake__.User'>
(Pdb) p value
<User: tutee>
(Pdb) p isinstance(value, self.field.remote_field.model._meta.concrete_model)
False
Вы используете функцию setup_test
внутри миграции . В миграции прямой импорт моделей, естественно, не будет работать, поскольку текущее состояние модели может отличаться от того, что ожидает конкретная миграция (см. заметки о исторических моделях в документации). Вы использовали функцию get_user_model
для получения модели пользователя и используете ее в своей функции, это просто использует некоторые функции для импорта модели пользователя, которую вы установили, поэтому вы получаете ошибку.
Следовательно, чтобы исправить это, вам нужно использовать apps.get_model
для получения модели пользователя:
def setup_test(apps, schema_editor):
User = apps.get_model('auth', 'User')
# In case of a custom user model replace above line like below comment
# User = apps.get_model('some_app', 'CustomUserModel')
User.objects.create_superuser("admin", "admin@gm.org", "123")
x = User.objects.create_user(
username="x", email="a@gm.org", password="123"
)
y = User.objects.create_user(
username="y", email="b@gm.org", password="123"
)
UserRelatinoship = apps.get_model("myapp", "UserRelatinoship")
UserRelatinoship.objects.create(x=x, y=y, active=True)