Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#30467 closed Cleanup/optimization (invalid)

`makemigrations app_label` sometimes tries to create migrations for unrequested app_label

Reported by: Vsevolod Novikov Owned by: nobody
Component: Migrations Version: 2.2
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The simplest scenario

Prerequisites

~/$ django-admin startproject mmbug
~/$ cd mmbug
~/mmbug$ python manage.py startapp app1
~/mmbug$ python manage.py startapp app2

Then modify settings.py:

...
INSTALLED_APPS = [
    ...
    'app1',
    'app2'
]

Then create models:

app1/models.py:

from django.db import models

# Create your models here.
class App1Model(models.Model):
    field1 = models.CharField(max_length=10)

app2/models.py:

from django.db import models

# Create your models here.
class App2Model(models.Model):
    field1 = models.CharField(max_length=10)
    field2 = models.ForeignKey('app1.App1Model', on_delete=models.CASCADE)

Then create a migration for app1:

~/mmbug$ python manage.py makemigrations app1

Then change app1 models file slightly and don't create migration for it:

app1/models.py:

from django.db import models

# Create your models here.
class App1Model(models.Model):
    field1 = models.CharField(max_length=10, verbose_name='Field 1')

What happens

The makemigrations command with applied app_label creates a migration for two app_labels

~/mmbug$ python manage.py makemigrations app2 --dry-run
Migrations for 'app1':
  app1/migrations/0002_auto_20190509_0823.py
    - Alter field field1 on app1model
Migrations for 'app2':
  app2/migrations/0001_initial.py
    - Create model App2Model

What I expect

The makemigrations command with applied app_label should create a migration for only noted app_label, probably with a warning, like

~/mmbug$ python manage.py makemigrations app2 --dry-run
Migrations for 'app2':
  app2/migrations/0001_initial.py
    - Create model App2Model

WARNING: the app1 application has uncovered changes in models, it may cause inconsistent migrations order

When it interferes

Let we have installed a third-party module

  • Case 1. Third-party package has model changes not covered by migration.
  • Case 2. Third-party package has model fields dependent on settings different in our project and installed package

If the module is installed in the virtualenv, the makemigrations command will create a messy migration in the site-packages subfolder.

Versions of Django

I reproduced this problem in Django 2.0, 2.1, and 2.2

Change History (4)

comment:1 by Carlton Gibson, 5 years ago

Resolution: invalid
Status: newclosed

Given the ForeignKey, this is expected behaviour, as explained in the Dependencies section of the Migrations documentation, and linked to from the makemigrations docs.

While migrations are per-app, the tables and relationships implied by your models are too complex to be created for just one app at a time. When you make a migration that requires something else to run - for example, you add a ForeignKey in your books app to your authors app - the resulting migration will contain a dependency on a migration in authors.

in reply to:  1 comment:2 by Vsevolod Novikov, 5 years ago

Resolution: invalid
Status: closednew

Replying to Carlton Gibson:

Given the ForeignKey, this is expected behaviour, as explained in the Dependencies section of the Migrations documentation, and linked to from the makemigrations docs.

While migrations are per-app, the tables and relationships implied by your models are too complex to be created for just one app at a time. When you make a migration that requires something else to run - for example, you add a ForeignKey in your books app to your authors app - the resulting migration will contain a dependency on a migration in authors.

This explanation doesn't contain any description of what happens. It just describes that the dependency section itself should contain references to another app migrations, but there is nothing about automatic creation of new migration in another application.

Existence of the table referred in the ForeignKey field (what's the documentation about really IMHO) is provided by the existent app1 migrations, so there is enough to have a reference to the last existent migration in the app1 instead of newly created, as it happens if no uncovered changes in the referred model are found:

...
    dependencies = [
        ('app1', '0001_initial'),
    ]
...

comment:3 by Carlton Gibson, 5 years ago

Resolution: invalid
Status: newclosed

The _Workflow_ above already says "...then a new set of migrations will be written out". That set is expected to include all the required dependencies, as per the section I linked.

Your suggestion for expected behaviour was this:

The makemigrations command with applied app_label should create a migration for only noted app_label...

But that's just not the correct behaviour. Hence closing as invalid.

Please see TicketClosingReasons/DontReopenTickets.

comment:4 by Vsevolod Novikov, 5 years ago

Discussion is continuing here: https://groups.google.com/forum/#!topic/django-developers/bSdMXi1sLcQ. Sorry for the inconvenience.

Note: See TracTickets for help on using tickets.
Back to Top