Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Don't be afraid of writing migrations

Markus H
April 01, 2016

Don't be afraid of writing migrations

Markus H

April 01, 2016
Tweet

More Decks by Markus H

Other Decks in Technology

Transcript

  1. from django.db import models class Book(models.Model): title = models.CharField(max_length=200) library

    = models.ForeignKey('Library') class Library(models.Model): name = models.CharField(max_length=200)
  2. from django.db import migrations, models class Migration(migrations.Migration): dependencies = []

    operations = [ migrations.CreateModel(name='Book', fields=[ ('id', models.AutoField(...)), ('title', models.CharField(max_length=200))])
  3. from django.db import migrations, models class Migration(migrations.Migration): dependencies = []

    operations = [ migrations.CreateModel(name='Book', fields=[ ('id', models.AutoField(...)), ('title', models.CharField(max_length=200))]), migrations.CreateModel(name='Library', fields=[ ('id', models.AutoField(...)), ('name', models.CharField(max_length=200))])
  4. from django.db import migrations, models class Migration(migrations.Migration): dependencies = []

    operations = [ migrations.CreateModel(name='Book', fields=[ ('id', models.AutoField(...)), ('title', models.CharField(max_length=200))]), migrations.CreateModel(name='Library', fields=[ ('id', models.AutoField(...)), ('name', models.CharField(max_length=200))]), migrations.AddField(model_name='book', name='library', field=models.ForeignKey(to='app.Library')) ]
  5. from django.db import migrations, models class Migration(migrations.Migration): dependencies = []

    operations = [ migrations.CreateModel(name='Library', fields=[ ('id', models.AutoField(...)), ('name', models.CharField(max_length=200)) ]), migrations.CreateModel(name='Book', fields=[ ('id', models.AutoField(...)), ('title', models.CharField(max_length=200)), ('library', models.ForeignKey(to='app.Library')) ]), ]
  6. $ python manage.py makemigrations Migrations for 'non_nullable_field': 0001_initial.py: - Create

    model Author $ python manage.py makemigrations non_nullable_field --empty --name initial_data Migrations for 'non_nullable_field': 0002_initial_data.py:
  7. from django.db import migrations def forwards(apps, schema_editor): Author = apps.get_model('non_nullable_field',

    'Author') Author.objects.create(name='Author 1') Author.objects.create(name='Author 2') def backwards(apps, schema_editor): Author = apps.get_model('non_nullable_field', 'Author') Author.objects.filter(name='Author 1').delete() Author.objects.filter(name='Author 2').delete() class Migration(migrations.Migration): dependencies = [('non_nullable_field', '0001_initial')] operations = [migrations.RunPython(forwards, backwards)]
  8. $ python manage.py migrate non_nullable_field Operations to perform: Apply all

    migrations: non_nullable_field Running migrations: Rendering model states... DONE Applying non_nullable_field.0001_initial... OK Applying non_nullable_field.0002_initial_data... OK
  9. from django.db import models class Author(models.Model): name = models.CharField(max_length=50) homepage

    = models.URLField(null=True) @classmethod def create(cls, name): return cls.objects.create(name=name)
  10. $ python manage.py makemigrations Migrations for 'non_nullable_field': 0003_author_homepage.py: - Add

    field homepage to author $ python manage.py migrate non_nullable_field Operations to perform: Apply all migrations: non_nullable_field Running migrations: Rendering model states... DONE Applying non_nullable_field.0003_author_homepage... OK
  11. from django.db import models from django.utils import html, safestring class

    Author(models.Model): name = models.CharField(max_length=50) homepage = models.URLField(null=True) @classmethod def create(cls, name, homepage): return cls.objects.create(name=name, homepage=homepage) @property def homepage_tag(self): if self.homepage: return html.format_html('<a href="{u}">{u}</a>', u=self.homepage) return safestring.mark_safe('<i>No homepage</i>')
  12. from django.db import migrations LOOKUP_DATA = {'Author 1': 'http://example.com', 'Author

    2': 'http://other.org'} def forwards(apps, schema_editor): Author = apps.get_model('non_nullable_field', 'Author') for author in Author.objects.filter(homepage__isnull=True): author.homepage = LOOKUP_DATA[author.name] author.save(update_fields=['homepage']) class Migration(migrations.Migration): dependencies = [('non_nullable_field', '0003_homepage')] operations = [ migrations.RunPython(forwards, migrations.RunPython.noop) ]
  13. $ python manage.py migrate non_nullable_field Operations to perform: Apply all

    migrations: non_nullable_field Running migrations: Rendering model states... DONE Applying non_nullable_field.0004_populate_data... OK
  14. from django.db import models from django.utils import html, safestring class

    Author(models.Model): name = models.CharField(max_length=50) homepage = models.URLField() @classmethod def create(cls, name, homepage): return cls.objects.create(name=name, homepage=homepage) @property def homepage_tag(self): if self.homepage: return html.format_html('<a href="{u}">{u}</a>', u=self.homepage) return safestring.mark_safe('<i>No homepage</i>')
  15. $ python manage.py makemigrations --name not_null_constraint You are trying to

    change the nullable field to non-nullable without a default ... Please select a fix: 1) Provide a one-off value ... 2) Ignore for now ... 3) Quit ... Select an option: 2 Migrations for 'non_nullable_field': 0005_not_null_constraint.py: - Alter field homepage on author
  16. from django.db import migrations, models class Migration(migrations.Migration): dependencies = [('non_nullable_field',

    '0004_populate')] operations = [ migrations.AlterField(model_name='author', name='homepage', field=models.URLField()) ]
  17. $ python manage.py migrate non_nullable_field Operations to perform: Apply all

    migrations: non_nullable_field Running migrations: Rendering model states... DONE Applying non_nullable_field.0005_not_null_constraint... OK
  18. from django.db import models from django.utils import html class Author(models.Model):

    name = models.CharField(max_length=50) homepage = models.URLField() @classmethod def create(cls, name, homepage): return cls.objects.create(name=name, homepage=homepage) @property def homepage_tag(self): return html.format_html('<a href="{u}">{u}</a>', u=self.homepage)
  19. # rename_app/models.py from django.db import models class Author(models.Model): name =

    models.CharField(max_length=50) class Book(models.Model): title = models.CharField(max_length=50) author = models.ForeignKey('rename_app.Author')
  20. $ python manage.py makemigrations $ python manage.py makemigrations rename_app --empty

    --name initial_data Edit rename_app/migrations/0002_initial_data.py $ python manage.py migrate rename_app
  21. # rename_app/models.py from django.db import models class Author(models.Model): name =

    models.CharField(max_length=50) class Meta: db_table = 'rename_app_author' class Book(models.Model): title = models.CharField(max_length=50) author = models.ForeignKey('rename_app.Author') class Meta: db_table = 'rename_app_book'
  22. $ python manage.py makemigrations --name pin_db_tables # rename_app/migrations/0003_pin_db_tables.py from django.db

    import migrations, models class Migration(migrations.Migration): dependencies = [('rename_app', '0002_initial_data')] operations = [ migrations.AlterModelTable(name='author', table='rename_app_author'), migrations.AlterModelTable(name='book', table='rename_app_book'), ] $ python manage.py migrate
  23. $ python manage.py migrate rename_app zero --fake Operations to perform:

    Unapply all migrations: rename_app Running migrations: Rendering model states... DONE Unapplying rename_app.0003_pin_db_tables... FAKED Unapplying rename_app.0002_initial_data... FAKED Unapplying rename_app.0001_initial... FAKED
  24. # in settings.py INSTALLED_APPS = [ # ... 'new_app_name.apps.NewAppNameConfig', ]

    # in new_app_name/models.py author = models.ForeignKey('new_app_name.Author') class Meta: db_table = 'rename_app_book' # Keep as is for now! # in new_app_name/migrations/0003_pin_db_tables.py and others dependencies = [('new_app_name', '0002_initial_data')]
  25. $ python manage.py migrate new_app_name --fake Operations to perform: Apply

    all migrations: new_app_name Running migrations: Rendering model states... DONE Applying new_app_name.0001_initial... FAKED Applying new_app_name.0002_initial_data... FAKED Applying new_app_name.0003_pin_db_tables... FAKED
  26. # new_app_name/models.py from django.db import models class Author(models.Model): name =

    models.CharField(max_length=50) class Book(models.Model): title = models.CharField(max_length=50) author = models.ForeignKey('new_app_name.Author')
  27. $ python manage.py makemigrations --name rename_tables # new_app_name/migrations/0004_rename_tables.py from django.db

    import migrations, models class Migration(migrations.Migration): dependencies = [('new_app_name', '0003_pin_db_tables')] operations = [ migrations.AlterModelTable(name='author', table=None), migrations.AlterModelTable(name='book', table=None), ] $ python manage.py migrate