#28438: Initial migration creates fields not listed in the migration if mixin 
class
changes
-----------------------------------------+------------------------
               Reporter:  Michal Dabski  |          Owner:  nobody
                   Type:  Uncategorized  |         Status:  new
              Component:  Uncategorized  |        Version:  1.11
               Severity:  Normal         |       Keywords:
           Triage Stage:  Unreviewed     |      Has patch:  0
    Needs documentation:  0              |    Needs tests:  0
Patch needs improvement:  0              |  Easy pickings:  0
                  UI/UX:  0              |
-----------------------------------------+------------------------
 Consider the sample model with a mixin class:
 {{{
 from django.db import models

 class TestMixin(object):
     pass


 class TestModel(TestMixin, models.Model):
     sample_field = models.CharField(max_length=20)
 }}}

 When running makemigrations, django creates a perfectly good and valid
 migration:
 {{{
 # -*- coding: utf-8 -*-
 # Generated by Django 1.11.3 on 2017-07-26 17:03
 from __future__ import unicode_literals

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


 class Migration(migrations.Migration):

     initial = True

     dependencies = [
     ]

     operations = [
         migrations.CreateModel(
             name='TestModel',
             fields=[
                 ('id', models.AutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('sample_field', models.CharField(max_length=20)),
             ],
             bases=(migration_test.models.TestMixin, models.Model),
         ),
     ]

 }}}
 SQL:

 {{{
 BEGIN;
 --
 -- Create model TestModel
 --
 CREATE TABLE "migration_test_testmodel" ("id" serial NOT NULL PRIMARY KEY,
 "sample_field" varchar(20) NOT NULL);
 COMMIT;
 }}}



 Next, refactor mixin class to add a field to it - need to change mixin's
 base class to {{{models.Model}}}, otherwise field will not be correctly
 inherited by models:
 {{{
 class TestMixin(models.Model):
     mixin_field = models.CharField(max_length=20, default='test')

     class Meta:
         abstract = True
 }}}

 Thie creates a new migration which adds {{{mixin_field}}} to it - nothing
 special. However, when applying both migrations after the model changes,
 second migration fails with the following error
 {{{django.db.utils.ProgrammingError: column "mixin_field" of relation
 "migration_test_testmodel" already exists}}}. as it turns out, the first
 migration's SQL has now changed to include {{{mixin_field}}}:
 {{{
 BEGIN;
 --
 -- Create model TestModel
 --
 CREATE TABLE "migration_test_testmodel" ("id" serial NOT NULL PRIMARY KEY,
 "mixin_field" varchar(20) NOT NULL, "sample_field" varchar(20) NOT NULL);
 COMMIT;
 }}}
 The python code of the migration obviously has not changed, but the
 resulting SQL did, and it includes a field not explicitly listed in the
 migration's {{{fields}}}.

 Note:
 - this does not happen if the mixin class extends {{{models.Model}}} to
 begin with.
 - if model extends a mixin that extends {{{object}}}, it ends up in
 model's {{{bases}}}, however if mixin extends {{{model.Model}}} it does
 not.



 Tested with Django 1.11.3, Python 2.7

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28438>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-updates+unsubscr...@googlegroups.com.
To post to this group, send email to django-updates@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/049.52ccadcb941c033f0bccb2404f914012%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to