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)
Вернуться на верх