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