Hi All,

The %subj% is a discussion for the ticket 
https://code.djangoproject.com/ticket/30467

The theme has been touched also in the following threads:
https://groups.google.com/forum/#!searchin/django-developers/makemigrations$20dependency%7Csort:date/django-developers/WgFacUFvgfs/cDoYO018NzIJ
https://groups.google.com/forum/#!searchin/django-developers/makemigrations|sort:date/django-developers/iClIpvwlbAU/53ZBk-y_AgAJ
https://groups.google.com/forum/#!searchin/django-developers/makemigrations|sort:date/django-developers/IG5ZSRRp8Rw/a0VSjrJMAQAJ

*What happens?*

Now, if the makemigration is running for the only app_label A, it sometimes 
tries to create a migration for other app_label B implicitly, if the A 
contains a *ForeignKey* field referring a model in the B with the 
unsynchronized state.

*What proposed?*

Always avoid implicit migration creation for the referred application B.

*Why the makemigrations CAN always do it?*

If the application A has a *ForeinKey* reference to the application B *without 
migrations*, it means, that all tables in the application B are already 
created on the stage of initial migration and need not be migrated.

If the *ForeignKey* in the application A refers to the *existent* (in the 
migration state) model of the application B, but with the *not synchronized 
state*, the created migration may depend on the last existent migration of 
the application A instead of newly created one almost anyway.

The only *inconsistent* unsynchronized change leading to possible errors 
may be:
- changing the *primary key* of the referred model in application B
- creating a *brand new referred model* in application B

Change in the primary key leads to changes in the ForeignKey field 
attributes, implicit, or explicit. Such a change may be detected separately 
and *agnostic* way: determining changes only in the ForeignKey field 
attribute values.
Non-existent referred model in the state can also be detected easy, and 
leads to other error detected on the stage of migration itself, or while 
runtime (non-existent table for the model).

Such an *inconsistent* unsynchronized change may lead to *error message* 
generated by the `makemigrations A`, like `the application A refers to the 
application B which needs to have synchronized migration state, please 
create a migration for B first`.

*Why the makemigrations SHOULD always do it?*

What is application B? It may be:

- own project application
- third-party application

If application B is own project application, the project owner always can 
explicitly create a new migration for the application B to synchronize its 
state. Such a way, it is enough to have an *error message* such described 
above instead of *implicit creation* of such a migration creating migration 
for application A.

The most problem is a third-party application.

The third-party application is such a thing that should not be changed by 
the programmer. It is installed in the system area or virtual environment 
as a rule.

If the third-party application B is installed into the system area, the 
`makemigration A` command will lead to file access error if tries to create 
a migration for application B automatically.
If the third-party application B is installed into the virtual environment, 
the `makemigration A` command will lead to migration conflict, and/or refer 
to non-existent migration in case of shared development of the project.

*Why the third-party application may have inconsistent migration state?*

1. Of course, the third-party application B can *really* have *inconsistent* 
migration state because of third-party programmers *error*. If such a 
problem is *significant* for the project, it is *detected* by the error 
message described above, or others, which allow the programmer of the 
project to make an *explicit decision*, what to do next.

The project programmer can create a lost (temporary) migration for 
application B, it is a resolution compatible with the existent now. He also 
can avoid using this application at all, create an issue in the tracker, 
etc... Anyway, the programmer makes a decision *explicitly* and knows about 
all the effects of it.

2. The inconsistent migration state may also be caused by dependencies of 
settings, different in the application when migration for B has been 
created, and project when the migration for A is created.

Such a dependency may lead to insignificant changes in the model state 
which don't change *ForeignKey* attributes. It might be changing in field 
verbose name, enum field choices, file field storage, or other field 
attributes not related to the database table metadata state.

Unfortunately, even the solution with the *__eq__ *substitution described 
in the documentation does not work to avoid unnecessary migration detection 
in such a case. A field attribute value of the complex deconstructible type 
leads to wrong state inconsistency detection when changed, even when have 
an *__eq__* substitution, because of doing *deep_deconstruct* results 
comparison instead of direct comparison in the Django code.

With best regards,
Vsevolod Novikov

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-developers+unsubscr...@googlegroups.com.
To post to this group, send email to django-developers@googlegroups.com.
Visit this group at https://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/907e3921-eafb-4036-b5cc-95647b9921f0%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to