There is an old MySQL database from a PHP site. I transferred it according to this documentation.

It turned out beautifully:

class Articles(models.Model): id_art = models.BigIntegerField(primary_key=True) id_section = models.BigIntegerField() id_t = models.BigIntegerField() id_ct = models.BigIntegerField() fesid = models.IntegerField() postpone_until = models.DateTimeField(blank=True, null=True) date_art = models.DateTimeField() status_art = models.CharField(max_length=3, blank=True, null=True) title_art = models.TextField() meta_art = models.TextField() short_art = models.TextField() full_art = models.TextField() foto_art = models.TextField(blank=True, null=True) foto_art_text = models.TextField(blank=True, null=True) sort_art = models.IntegerField() map_art = models.TextField(blank=True, null=True) coordinates_art = models.TextField() vk_id = models.CharField(max_length=40) nl2br = models.IntegerField() id_man = models.IntegerField() class Meta: managed = True db_table = 'articles' 

Then I remade it for the needs of a new project in several migrations. It turned out something like this:

 class Articles(models.Model): id_art = models.AutoField(primary_key=True) title_art = models.CharField(verbose_name='Заголовок', max_length=250) id_section = TreeForeignKey(SectionArt, db_column='id_section', verbose_name='Категория') fesid = models.ForeignKey(Fedsubj, db_column='fesid', verbose_name='Регион') id_ct = ChainedForeignKey( Cities, chained_field='fesid', chained_model_field='fesid', show_all=False, auto_choose=True, db_column='id_ct', verbose_name='Город' ) created_at = models.DateTimeField( verbose_name='Дата создания', blank=True, null=True, auto_now_add=True, db_column='date_art', ) meta_art = models.TextField(null=True, blank=True, verbose_name='Мета') short_art = models.TextField(verbose_name='Короткое описание', max_length=300) full_art = RichTextUploadingField(verbose_name='Содержание') foto_art = models.ImageField(blank=True, null=True, verbose_name='Изображение') foto_art_text = models.TextField(blank=True, null=True, verbose_name='Описание изображения') coordinates_art = models.TextField(blank=True, null=True, verbose_name='Координаты') class Meta: managed = True db_table = 'articles' verbose_name = u'Новость' verbose_name_plural = u'Новости' def __unicode__(self): return self.title_art def category_name(self): return self.id_section.get_root().title_sec category_name.short_description = u'Раздел' 

And now something very strange happens during the migration:

 django.db.utils.OperationalError: (1292, "Incorrect datetime value: '0000-00-00 00:00:00' for column 'postpone_until' at row 3595") 

Although I have already deleted the `postpone_until 'in my migration. By the way, here it is:

 operations = [ migrations.RemoveField( model_name='articles', name='date_art', ), migrations.RemoveField( model_name='articles', name='id_man', ), migrations.RemoveField( model_name='articles', name='id_t', ), migrations.RemoveField( model_name='articles', name='map_art', ), migrations.RemoveField( model_name='articles', name='nl2br', ), migrations.RemoveField( model_name='articles', name='postpone_until', ), migrations.RemoveField( model_name='articles', name='sort_art', ), migrations.RemoveField( model_name='articles', name='status_art', ), migrations.RemoveField( model_name='articles', name='vk_id', ), migrations.AddField( model_name='articles', name='created_at', field=models.DateTimeField(auto_now_add=True, db_column='date_art', null=True, verbose_name='\u0414\u0430\u0442\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f'), ), migrations.AlterField( model_name='articles', name='coordinates_art', field=models.TextField(blank=True, null=True, verbose_name='\u041a\u043e\u043e\u0440\u0434\u0438\u043d\u0430\u0442\u044b'), ), migrations.AlterField( model_name='articles', name='fesid', field=models.ForeignKey(db_column='fesid', on_delete=django.db.models.deletion.CASCADE, to='articles.Fedsubj', verbose_name='\u0420\u0435\u0433\u0438\u043e\u043d'), ), migrations.AlterField( model_name='articles', name='foto_art', field=models.ImageField(blank=True, null=True, upload_to=b'', verbose_name='\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435'), ), migrations.AlterField( model_name='articles', name='foto_art_text', field=models.TextField(blank=True, null=True, verbose_name='\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f'), ), migrations.AlterField( model_name='articles', name='full_art', field=ckeditor_uploader.fields.RichTextUploadingField(verbose_name='\u0421\u043e\u0434\u0435\u0440\u0436\u0430\u043d\u0438\u0435'), ), migrations.AlterField( model_name='articles', name='id_art', field=models.AutoField(primary_key=True, serialize=False), ), migrations.AlterField( model_name='articles', name='id_ct', field=smart_selects.db_fields.ChainedForeignKey(auto_choose=True, chained_field='fesid', chained_model_field='fesid', db_column='id_ct', on_delete=django.db.models.deletion.CASCADE, to='articles.Cities', verbose_name='\u0413\u043e\u0440\u043e\u0434'), ), migrations.AlterField( model_name='articles', name='id_section', field=mptt.fields.TreeForeignKey(db_column='id_section', on_delete=django.db.models.deletion.CASCADE, to='articles.SectionArt', verbose_name='\u041a\u0430\u0442\u0435\u0433\u043e\u0440\u0438\u044f'), ), migrations.AlterField( model_name='articles', name='meta_art', field=models.TextField(blank=True, null=True, verbose_name='\u041c\u0435\u0442\u0430'), ), migrations.AlterField( model_name='articles', name='short_art', field=models.TextField(max_length=300, verbose_name='\u041a\u043e\u0440\u043e\u0442\u043a\u043e\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435'), ), migrations.AlterField( model_name='articles', name='title_art', field=models.CharField(max_length=250, verbose_name='\u0417\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u043a'), ), ] 

How to deal with it?


UPD

sqldiff just sqldiff me up

  ALTER TABLE `articles` DROP COLUMN `id_t`; ALTER TABLE `articles` DROP COLUMN `postpone_until`; ALTER TABLE `articles` DROP COLUMN `status_art`; ALTER TABLE `articles` DROP COLUMN `sort_art`; ALTER TABLE `articles` DROP COLUMN `map_art`; ALTER TABLE `articles` DROP COLUMN `vk_id`; ALTER TABLE `articles` DROP COLUMN `nl2br`; ALTER TABLE `articles` DROP COLUMN `id_man`; CREATE INDEX `articles_id_section` ON `articles` (`id_section`); CREATE INDEX `articles_fesid` ON `articles` (`fesid`); CREATE INDEX `articles_id_ct` ON `articles` (`id_ct`); ALTER TABLE `articles` MODIFY `id_art` integer AUTO_INCREMENT; ALTER TABLE `articles` MODIFY `title_art` varchar(250); ALTER TABLE `articles` MODIFY `id_section` integer; ALTER TABLE `articles` MODIFY `foto_art` varchar(100); ALTER TABLE `articles` MODIFY `date_art` DROP NOT NULL; ALTER TABLE `articles` MODIFY `meta_art` DROP NOT NULL; ALTER TABLE `articles` MODIFY `coordinates_art` DROP NOT NULL; 
  • Install django-extensions and try to see what the difference is through the sqldiff command - this will show what could have migrated incorrectly, for example. Further we will look by circumstances - FeroxTL
  • one
    By the way, what is the base? Googles on a similar subject mysql, but this is only speculation - FeroxTL
  • not quite on the topic, but: do not conclude a bunch of operations in the migration, one operation = one migration. this eliminates the possibility of a pending state and any troubles with reordering operations (what this example is very similar to). - etki
  • @Etki what you see - 14th migration - Viktor
  • @Etki you can interfere with several operations in one migration, this is normal practice. It is better not to mix datamigration and schemamigration, yes it is - FeroxTL

2 answers 2

I will assume, by sqldiff, that the real migration from you was not completed, which should have removed the columns, was not completed.

I have already talked about the internal structure of the migration system in django . In general, I have a suspicion that the internal migration system django believes that you have managed = False (despite the fact that the opposite is true). Either I counted at some period of time (at this time the migrations most likely worked fakely for you, although they were visually applied). You can check this with the same django-extensions function sqlmigrate , pointing it to one of those migrations that should have removed the columns, but did not perform this. Example:

 ./manage.py sqlmigrate core 0018 

If sql is displayed, then my assumptions are false and then you can not read.

What needs to be checked further

First, find the migration that directly created this table. Unfortunately having rummaged in the projects I did not find that kommit whom I corrected at myself a similar bug. It should look something like this - better find and display in the question

  migrations.CreateModel(name=u'Profile', fields=[( # ... ], options={}, bases=(u'accounts.baseuser',), managers=[ # ... ]), 

We are interested in the options dictionary — sometimes swappable , managed = False , proxy = True and other constructions get there. It is necessary to check this dictionary for data structures If there are - delete, roll back migration to the desired place (in order not to lose data, look at the situation) and re-run

    I found the cause of the error: in the postpone_until column, one of the entries had 00.00.0000 00:00:00 . After manual removal, the migration is working. Only here all the dates from date_art left.


     ALTER TABLE `articles` DROP COLUMN `id_t`; ALTER TABLE `articles` DROP COLUMN `postpone_until`; ALTER TABLE `articles` DROP COLUMN `status_art`; ALTER TABLE `articles` DROP COLUMN `sort_art`; ALTER TABLE `articles` DROP COLUMN `map_art`; ALTER TABLE `articles` DROP COLUMN `vk_id`; ALTER TABLE `articles` DROP COLUMN `nl2br`; ALTER TABLE `articles` DROP COLUMN `id_man`; CREATE INDEX `articles_id_section` ON `articles` (`id_section`); CREATE INDEX `articles_fesid` ON `articles` (`fesid`); CREATE INDEX `articles_id_ct` ON `articles` (`id_ct`); ALTER TABLE `articles` MODIFY `id_art` integer AUTO_INCREMENT; ALTER TABLE `articles` MODIFY `title_art` varchar(250); ALTER TABLE `articles` MODIFY `id_section` integer; ALTER TABLE `articles` MODIFY `foto_art` varchar(100); ALTER TABLE `articles` MODIFY `date_art` DROP NOT NULL; ALTER TABLE `articles` MODIFY `meta_art` DROP NOT NULL; ALTER TABLE `articles` MODIFY `coordinates_art` DROP NOT NULL; 
    • So you have no migration applied judging by the sqldiff, how did it work? - FeroxTL
    • So after eliminating this error, they applied - Viktor
    • It was worthwhile even then to display the list of applied migrations, I thought you suddenly had all the beginning to pour in - FeroxTL
    • @FeroxTL is just the point. After all, the removal of the old column and the creation of a new one were stuck in one migration. gist.github.com/dukeimg/9d8d1b0cfe5ecb986b0009266924b2ed So Etki is somewhat right: simplifying migration makes it easier to track errors. - Viktor