#25145: Models of apps w/o migrations don't have relational fields to other apps w/o migrations when applying migrations --------------------------------------+------------------------ Reporter: MarkusH | Owner: nobody Type: Bug | Status: new Component: Migrations | Version: 1.8 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 three apps `w_migrations`, `wo_migrations1` and `wo_migrations2` with the following models:
`w_migrations`: {{{#!python class With(models.Model): without1 = models.ForeignKey('wo_migrations1.Without1') }}} `wo_migrations1`: {{{#!python class Without1(models.Model): without2 = models.ForeignKey('wo_migrations2.Without2') }}} `wo_migrations2`: {{{#!python class Without2(models.Model): i = models.IntegerField() }}} When you create the migration for `w_migrations` and add an additional `RunPython` operation: {{{#!python def forward(apps, schema_editor): print(apps.get_model('wo_migrations1', 'Without1')._meta._get_fields()) operations = [ ..., migrations.RunPython(forward, migrations.RunPython.noop), ] }}} you will get the following output: {{{#!python (<django.db.models.fields.AutoField: id>,) }}} However, one would expect to see the `ForeignKey` to `wo_migrations2`, too. A fix should be rather simple by updating `django.db.migrations.state.ModelState.from_model()` similar to those lines: {{{#!diff diff --git a/django/db/migrations/state.py b/django/db/migrations/state.py index b1cba07..4dd25ba 100644 --- a/django/db/migrations/state.py +++ b/django/db/migrations/state.py @@ -219,7 +219,7 @@ class StateApps(Apps): for app_label in real_apps: app = global_apps.get_app_config(app_label) for model in app.get_models(): - self.real_models.append(ModelState.from_model(model, exclude_rels=True)) + self.real_models.append(ModelState.from_model(model, exclude_rels=True, allow_rels_to=real_apps)) # Populate the app registry with a stub for each application. app_labels = {model_state.app_label for model_state in models.values()} app_configs = [AppConfigStub(label) for label in sorted(real_apps + list(app_labels))] @@ -346,14 +346,15 @@ class ModelState(object): return self.name.lower() @classmethod - def from_model(cls, model, exclude_rels=False): + def from_model(cls, model, exclude_rels=False, allow_rels_to=[]): """ Feed me a model, get a ModelState representing it out. """ # Deconstruct the fields fields = [] for field in model._meta.local_fields: - if getattr(field, "remote_field", None) and exclude_rels: + if (exclude_rels and field.is_relation and + _get_app_label_and_model_name(field.related_model)[0] not in allow_rels_to): continue if isinstance(field, OrderWrt): continue @@ -367,18 +368,20 @@ class ModelState(object): model._meta.label, e, )) - if not exclude_rels: - for field in model._meta.local_many_to_many: - name, path, args, kwargs = field.deconstruct() - field_class = import_string(path) - try: - fields.append((name, field_class(*args, **kwargs))) - except TypeError as e: - raise TypeError("Couldn't reconstruct m2m field %s on %s: %s" % ( - name, - model._meta.object_name, - e, - )) + for field in model._meta.local_many_to_many: + if (exclude_rels and field.is_relation and + _get_app_label_and_model_name(field.related_model)[0] not in allow_rels_to): + continue + name, path, args, kwargs = field.deconstruct() + field_class = import_string(path) + try: + fields.append((name, field_class(*args, **kwargs))) + except TypeError as e: + raise TypeError("Couldn't reconstruct m2m field %s on %s: %s" % ( + name, + model._meta.object_name, + e, + )) # Extract the options options = {} for name in DEFAULT_NAMES: }}} I believe this bug is also present on 1.8, haven't investigated though. If it is, it is I think it is a regression from 1.7 to 1.8. -- Ticket URL: <https://code.djangoproject.com/ticket/25145> 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/050.4a46f79087def1532c3954e516d3e626%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.