Welcome to the Treehouse Community

The Treehouse Community is a meeting place for developers, designers, and programmers of all backgrounds and skill levels to get support. Collaborate here on code errors or bugs that you need feedback on, or asking for an extra set of eyes on your latest project. Join thousands of Treehouse students and alumni in the community today. (Note: Only Treehouse students can comment or ask questions, but non-students are welcome to browse our conversations.)

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and a supportive community. Start your free trial today.

Python Improve a Django Project

Alx Ki
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Alx Ki
Python Web Development Techdegree Graduate 14,810 Points

Data Migration from DateTimeField to DateField.

Kenneth Love , Hello again! Seems like I need help.

I wrote a custom data migration according to docs:

from datetime import datetime
from django.db import models, migrations



def datetime_to_date(apps, schema_editor):
    Menu = apps.get_model("menu", "Menu")
    for menu in Menu.objects.all():
        if menu.expiration_date:
            menu.expiration_date = datetime.date(menu.expiration_date)
            menu.save()
        if menu.created_date:
            menu.created_date = datetime.date(menu.created_date)
            menu.save()

    Item = apps.get_model('menu', 'Item')
    for item in Item.objects.all():
        if item.created_date:
            item.created_date = datetime.date(item.created_date)
            item.save()


class Migration(migrations.Migration):

    dependencies = [
        ('menu', '0003_auto_20170105_1341'),
    ]

    operations = [
        migrations.RunPython(datetime_to_date),
    ]

And now a stupid question: The first time i ran it it worked.

But i made a lot of problems, then reverted, started again, and... I can't do that data migration as I want it.

The question is: What is the order, I mean change model fields -> makemigrations -> migrate -> run my custom data migration or what?

3 Answers

Chris Howell
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Howell
Python Web Development Techdegree Graduate 49,610 Points

Hi alexey kislitsin

So yes normally you want to:

  1. Change a Model Field
  2. Run python manage.py makemigrations
  3. Run python manage.py migrate

According to the Migrations Docs

makemigrations - which is responsible for creating new migrations based on the changes you have made to your models.

migrate - which is responsible for applying and unapplying migrations.

So makemigrations will create your migration files which you can find under the migrations folder for each app. Then running migrate will actually make those changes into the database. So normally you wont run a migrate unless you have new changes inside your migrations file. Which you will only have new changes in your migrations file if you have changed something in your models.py and ran makemigrations to have the new migrations created.

Does that make sense?

Alx Ki
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Alx Ki
Python Web Development Techdegree Graduate 14,810 Points

Hi, Chris Howell ! Thank you for your answer Yes, I understand it.

For example I made schema migration:

  1. I changed model field from DatetimeField to DateField.
  2. I made migrations for it and applied it.

Now I wand to make data migration in database from datetime to date:

I run my custom migration but data doesnt change properly. How do I perform data change in database?

Alx Ki
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Alx Ki
Python Web Development Techdegree Graduate 14,810 Points

Ok. So, I didn't find the way I did the data migration the first time, so I decided to recreate the fields... It s totally not what I wanted, but it works.

Algorythm:

  1. Add new field.
  2. Copy the changed data in new field.
  3. Remove old field.
  4. Rename new field.

If someone knows how to avoid creating new field - please tell me! I did it somehow accidentally.. but unfortunately i can not remember how.

Chris Howell
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Chris Howell
Python Web Development Techdegree Graduate 49,610 Points

Hi alexey kislitsin

I feel like there is a miscommunication/misinterpretation/misunderstanding of sorts between my answer and your question.

So initially I was trying to understand why you were manually writing migration files when you dont have to. Django does that for you with makemigrations then even applies those migrations to the database with the migrate command.

If I am understanding this right. Basically you are wanting to physically move data in each row of a column into a new column?

Then you may want to be looking at these docs for Data Migrations

I imagine you could basically write a function similar to how they did their def combine_names function in the example and save old entries into your new field.

If you combine that with the dumpdata command you could first do a dumpdata of your current model and output your data into a JSON file. Then you would likely have to write a function that looks for the old fields in the JSON but saves to the new field of the migrated model. This is probably how I would approach it.

or I think another way could be...

You could change your model field adding the new field. Leaving the old field with all the data still there. Run makemigrations and migrate.

Then write a script that does a Model.objects.all() (where Model is name of your Model) or you can even select just the field you want to change. Loop over each item in the database grabbing the old field value and updating the new field with the same data.

Then afterward you can change the model field removing the old field.

Alx Ki
seal-mask
.a{fill-rule:evenodd;}techdegree seal-36
Alx Ki
Python Web Development Techdegree Graduate 14,810 Points

Chris Howell , well finally that another way is actually how i did it. I just thought there is a simpler way to migrate schema and data in one step right inside the field. Thank You!