pythondjangopython-2.7django-modelsdjango-1.10

ForeignKey to 'self' in sub-application throws error on makemigrations in Django project


I'm currently working on an large Django project (version 1.10.7) and am running into an error with a model field in a sub-application. Here's what the basic structure looks like:

project/
    app_one/
        __init__.py
        apps.py
        models.py
        urls.py
        views.py
        app_two/
            __init__.py
            apps.py
            models.py
            urls.py
            views.py

The model and field in question looks like this (project/app_one/app_two/models.py):

class SampleModel(model.Model):
    parent = models.ForeignKey('self', null=True, blank=True, related_name='members')

When I run python manage.py makemigrations app_one.app_two in the root folder I get this error message:

File .../django/db/models/utils.py", line 23, in make_model_tuple "must be of the form 'app_label.ModelName'." % model ValueError: Invalid model reference 'app_one.app_two.SampleModel'. String model references must be of the form 'app_label.ModelName'.

Here is code from other files that are relevant:

project/settings.py:

INSTALLED_APPS = filter(None, (
    ...
    'app_one',
    'app_one.app_two',
    ...
)

project/app_one/app_two/apps.py:

from __future__ import unicode_literals

from django.apps import AppConfig


class AppOneAppTwoConfig(AppConfig):
    name = 'app_one.app_two'
    label = 'app_one.app_two'

project/app_one/app_two/__init__.py:

default_app_config = 'app_one.app_two.apps.AppOneAppTwoConfig'

I believe the error here is that Django is only looking for one . in the full model name (app_one.app_two.SampleModel) to separate the app label from the model name in django/db/models/utils.py, and since there are two in this case, it fails.

My question is: This seems like a weird for Django not to account for...is there anyway to retain the dot notation of the app label and still have a self-referencing ForeignKey in a sub-application?


Solution

  • As you mention, it seems to be a lookup error when the project is trying to locate your app due to the nested apps. This can be solved by specifying the app name with an app_label in the models internal meta class:

    class SampleModel(models.Model):
        ...
        class Meta:
            app_label = 'app_two'