Home > database >  Creating a new model with a one-to-one relationship with an existing model Django
Creating a new model with a one-to-one relationship with an existing model Django

Time:11-18

I want to add a Profile model relationship through a one-to-one field to the existing User model. However I already have a couple of users in the database. How can I migrate the new model while creating these default relationships at the same time?

So for example I have two users Foo and Bar already created in the database and after migrating the Profile model both users should have an associated Profile with them.

Models

class User(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(verbose_name="Email Address", max_length=255, unique=True)
    first_name = models.CharField(max_length=255)
    surname = models.CharField(max_length=255)

    is_active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False)
    admin = models.BooleanField(default=False)

    objects = UserManager()

    USERNAME_FIELD = "email"
    REQUIRED_FIELDS = ["first_name", "surname"]

    def get_full_name(self):
        return f"{self.first_name} {self.surname}"

    def __str__(self):
        return self.email

    def is_staff(self):
        return self.staff

    def is_admin(self):
        return self.admin

### New model I want to create
class Profile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    avatar = models.ImageField(default="gravatar.jpg", upload_to="avatars/")
    username = models.CharField(max_length=255, blank=True)
    phone = models.CharField(max_length=15, blank=True)

    def __str__(self):
        return f"{self.user.first_name}'s profile"

CodePudding user response:

In the newly created migration file simply include a RunPython script which will create related Profile objects for the existing users:

# xxxx_migration.py file

from django.db import migrations


def create_profiles(apps, schema_editor):
    User = apps.get_model(<app_name>, 'User')
    Profile = apps.get_model(<app_name>, 'Profile')
    users = User.objects.filter(profile__isnull=True)
    Profile.objects.bulk_create(
        [Profile(user=user, username=user.email) for user in users]
    )


class Migration(migrations.Migration):
    dependencies = [<migration_dependencies>]

    operations = [
        migrations.CreateModel(
            name='Profile',
            fields=[...]
        ),

        # Create profile objects
        migrations.RunPython(create_profiles, reverse_code=migrations.RunPython.noop)
    ]

More about custom scripts in migrations here

  • Related