Home > Mobile >  Django: ValueError: Cannot assign "<User: x>": "UserRelatinoship.x" must b
Django: ValueError: Cannot assign "<User: x>": "UserRelatinoship.x" must b

Time:09-27

I am trying to automatically create a relationship between two test users in a migration in Django. My migration code looks like this:

# 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", "[email protected]", "123")
    x = User.objects.create_user(
        username="x", email="[email protected]", password="123"
    )
    y = User.objects.create_user(
        username="y", email="[email protected]", 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),
    ]

Model Code

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}"

The users are created fine, but then when I try to create the relationship I get the error ValueError: Cannot assign "<User: x>": "UserRelatinoship.x" must be a "User" instance.. Also, I can create the relationship while running the server and filling out forms manually, even though the code for that looks about identical (except it uses request.user for one part). Note I modified some names from my original code. Any help is greatly appreciated!

CodePudding user response:

You use the function setup_test inside a migration. In a migration directly importing models will naturally not work because the current model state might be different from what the specific migration expects (See notes about Historical models in the documentation). You have used the get_user_model function to get the user model and are using that in your function, this will simply use some functions to import the user model that you have set, hence you get the error.

Hence to fix this you need to use apps.get_model to get the user 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", "[email protected]", "123")
    x = User.objects.create_user(
        username="x", email="[email protected]", password="123"
    )
    y = User.objects.create_user(
        username="y", email="[email protected]", password="123"
    )
    UserRelatinoship = apps.get_model("myapp", "UserRelatinoship")
    UserRelatinoship.objects.create(x=x, y=y, active=True)
  • Related