Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#22758 closed Bug (invalid)

Makemigrations puts subclasses of abstract models in the wrong app

Reported by: Craig de Stigter Owned by: Aymeric Augustin
Component: Core (Other) Version: 1.7-beta-2
Severity: Release blocker Keywords: app-loading
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


If I define a concrete model that inherits an abstract base from a different app, like so:

class AbstractModel(models.Model):
    a = models.CharField(max_length=100)

    class Meta:
        abstract = True
        app_label = 'otherapp'

class MyModel(AbstractModel):
    b = models.CharField(max_length=255)

Then makemigrations tells me nothing has changed.

$ ./ makemigrations foo
No changes detected in app 'foo'

Because it's assigned my model to the app containing the abstract class:

$ ./ makemigrations otherapp
Migrations for 'otherapp':
    - Create model MyModel

There is a workaround: If I instead explicitly supply app_label on my model it works as expected:

class MyModel(AbstractModel):
    b = models.CharField(max_length=255)

    class Meta:
        app_label = 'foo'
$ ./ makemigrations foo
Migrations for 'foo':
    - Create model MyModel

Change History (7)

comment:1 Changed 4 years ago by Andrew Godwin

Component: MigrationsCore (Other)

This looks to be a problem in app loading - I've confirmed that on 1.6 it's fine, on 1.7 even get_models() puts it in the wrong app. Reassigning component, will come back around to fix after migrations if nobody else gets there.

comment:2 Changed 4 years ago by Andrew Godwin

Also worth noting: This only occurs with an explicit app_label declaration. It's fine if the models just normally live in the separate apps' model files.

comment:3 Changed 4 years ago by Craig de Stigter

This only occurs with an explicit app_label declaration

That wasn't my experience. I encountered the issue with django-typed-models, where the abstract model was located in the typedmodels app, and the concrete model was in some other app.

comment:4 Changed 4 years ago by Aymeric Augustin

Keywords: app-loading added
Owner: changed from nobody to Aymeric Augustin
Status: newassigned

comment:5 Changed 4 years ago by Aymeric Augustin

(removed misleading comment)

Last edited 4 years ago by Aymeric Augustin (previous) (diff)

comment:6 Changed 4 years ago by Aymeric Augustin

Resolution: invalid
Status: assignedclosed

You're seeing the documented behavior. If you set an app_label, it will be inherited by child classes, like all Meta attributes except abstract = True:

Abstract models don't do anything with their app_label as they aren't added to the app registry. The only purpose of providing an app_label is to make it apply to inherited classes.

If Django didn't behave that way in previous versions, that was a bug, and it has been fixed.

Also, note the existence of the opposite ticket for proxy models: #11078.

comment:7 Changed 4 years ago by Craig de Stigter

Okay, I guess that makes sense. For context, I was doing this because I was getting this deprecation warning:

~/code/django-typed-models/typedmodels/ RemovedInDjango19Warning: Model class typedmodels.models.TypedModel doesn't declare an explicit app_label and either isn't in an application in INSTALLED_APPS or else was imported before its application was loaded. Its app_label will be set to None in Django 1.9.

... but with a fresh coffee it seems I'm not getting it any more. Probably some error on my part. Thanks :)

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