简体   繁体   中英

Django - Is it possible to split a single model class into two model classes, while preserving the data from before split?

In Django is it possible to split a single model class into two model classes, while preserving the data that was previously entered?

Initial Model:

class Fruit(models.Model):
    name = models.CharField(max_length=100)
    color = models.CharField(max_length=100)
    taste_description = models.CharField(max_length=100)
    tasty = models.BooleanField()

Split Models:

class Fruit(models.Model):
    name = models.CharField(max_length=100)
    color = models.CharField(max_length=100)

class Fruittaste(models.Model):
    fruit = models.ForeignKey(Fruit, on_delete=models.CASCADE)
    taste_description = models.CharField(max_length=100)
    tasty = models.BooleanField()

There isn't any easy or single command way to do this. It can be done by:

  1. Create a new model but keep the origonal model intact, ie don't remove any fields

  2. Run a script to transfer all data to new model

  3. Run tests to see if your code and views are working properly

  4. Remove the unneeded and old fields in the main model at your leisure

Hope it helps!

1/ create your new model, leaving the original unchanged

2/ make a migration to create the model, run it, add it to your version control

3/ create an empty migration for your app, and in this migration write the data migration code

def forward(apps, schema_editor):
    # VERY important: don't import the models, 
    # get them from `app.get_model()`
    Fruit = apps.models.get("yourappname", "Fruit")
    Fruittaste = apps.models.get("yourappname", "Fruittast")

    data = [        Fruittaste(fruit=fruit,taste_description=fruit.tase_description,tasty=fruit.tasty) for fruit in Fruit.objects.all()
    ]
    Fruittaste.objects.bulk_create(data)


class Migration(migrations.Migration):

    dependencies = [
        ('yourappname', '000x_previous_migration'),
    ]

    operations = [
        migrations.RunPython(forward),
    ]

NB: depending on your dataset size, you can also write the new records to db one by one instead of collecting them in a list and send the whole to bulk_create. This will be slower, but it will eat less memory.

NB: You should add a backward migration whenever possible, but in your above case you'd have to arbitrarily choose one of the many possible tastes for each fruit so...

4/ and finally remove the now obsolete fields from Fruit , make and run the migration etc (nb do no forget to add your migration files to your version cotrol.!!).

  • Step 1: create Fruittaste model, and run migrations (without changing Fruit )

  • Step 2: execute the following query to populate Fruittase .

     data = [] from.models import Fruit, Fruittaste for fruit in Fruit.objects.all(): data.append( Fruittaste( fruit = fruit, taste_description = fruit.tase_description, tasty = fruit.tasty )) Fruittaste.objects.bulk_create(data)

Now you can delete the duplicate rows from Fruit , and run migrations again.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM