Taehwan Kim
Taehwan Kim

Reputation: 31

Data migrations for OneToOneField in django

I have a Product model and I want to extend by using OneToOneField.

For example

class Product:
    name = models.CharField(..)
    price = models.FloatField(...)

I want to do like this

class MyProduct:
    product = models.OneToOneField(myapp.Product, on_delete=models.CASCADE)
    location = models.CharField(...)

and using signal

def create_myproduct(sender, instance, created, **kwargs):
    """Create MyProduct class for every new Product"""
    if created:
        MyProduct.objects.create(product=instance)

signals.post_save.connect(create_myproduct, sender=Product, weak=False,
                          dispatch_uid='models.create_myproduct')

This works for newly created Product, so I can do like this in template.

{{ product.myproduct.location }}

But Old products that created before adding this OneToOneRelation,has no field 'myproduct' and that template code didn't work.

I heard I need a data migrations for old product using RunPython or manage.py shell. Can you teach me how to do? I read a documentation from django, but still don't fully understand.

Upvotes: 2

Views: 1993

Answers (3)

m.antkowicz
m.antkowicz

Reputation: 13571

You should just migrate your models in a normal way

python manage.py makemigrations
python manage.py migrate 

During making migrations you will be asked how to fill new fields for existing data

Please notice that when you are using Django under 1.7 version you do not have migrations (and syncdb will not do the job for existing tables) - consider using the 3rd part tool like south

Upvotes: 1

Taehwan Kim
Taehwan Kim

Reputation: 31

I just found out.

Like Rohit Jain said product.myproduct is None.

When I tried to access product.myproduct, I got an exception that object does not exist. It has a relation to myproduct but the actual object doesn't exist.

What I really want was creating MyProduct object and add it to Product class.

So I did it in python manage.py shell

products = Product.objects.all()
for prod in products:
    if not hasattr(prod, 'myproduct'):
        prod.myproduct = MyProduct.objects.create(product=prod)
        prod.save()

I think it works for me now.

Thank you guys

Upvotes: 1

milad faraji
milad faraji

Reputation: 21

you can add new migration. and apply it. something like this code:

# -*- coding: utf-8 -*-
# Generated by Django 1.11.2 on 2017-07-22 06:04
from __future__ import unicode_literals

from django.db import migrations, models


def create_myproducts(apps, schema_editor):
    Product = apps.get_model('myapp', 'Product')
    MyProduct = apps.get_model('myapp', 'MyProduct')
    for prod in Product.objects.all():
        MyProduct.objects.create(product=prod)


class Migration(migrations.Migration):

    dependencies = [
        ('myapp', 'your last migration'),
    ]

    operations = [
        migrations.RunPython(create_myproducts)
    ]

Upvotes: 2

Related Questions