Создание новой модели, имеющей связь один-к-одному с существующей моделью Django

Я хочу добавить отношение модели Profile через поле один-к-одному к существующей модели User. Однако у меня уже есть несколько пользователей в базе данных. Как я могу перенести новую модель, одновременно создавая эти отношения по умолчанию?

Например, у меня есть два пользователя Foo и Bar, уже созданные в базе данных, и после миграции модели Profile оба пользователя должны иметь связанные с ними Profile.

Модели

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"

Во вновь созданный файл миграции просто включите RunPython скрипт, который создаст связанные Profile объекты для существующих пользователей:

# 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)
    ]

Подробнее о пользовательских скриптах в миграциях здесь

Вернуться на верх