приложение django с дополнительными приложениями. app_labels для подприложений и отношения внешнего ключа между ними

Я пытаюсь создать приложение django с несколькими дочерними приложениями. Мой текущий макет каталога для приложения (для краткости отфильтрованы admin.py, test.py и views.py):

myapp
    __init__.py
    models.py
    subapp1/
        __init__.py
        models.py
    subapp2
        __init__.py
        models.py

Где myapp/models.py выглядит так:

class Foo(models.Model):
    name = models.CharField(max_length=32)

и myapp/subapp1/models.py выглядит так:

class Bar(models.Model):
    foo = models.ForeignKey('myapp.Foo')
    some_other_field = models.CharField(max_length=32)

и myapp/subapp2/models.py выглядит так:

class Baz(models.Model):
    bar = models.ForeignKey('subapp1.Bar')

В моем settings.py у меня есть:

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
    'myapp.subapp1',
    'myapp.subapp2'
)

Однако, когда я пытаюсь запустить ./manage.py makemigrations myapp.subapp1, я получаю сообщение об ошибке:

App 'myapp.subapp1' could not be found. Is it in INSTALLED_APPS?

Но я могу успешно запустить ./manage.py makemigrations subapp1 и эквивалент для subapp2. Что меня беспокоит, так это коллизии пространств имен приложений.

Если я добавлю myapp/subapp1/apps.py

from django.apps import AppConfig

class SubApp1Config(AppConfig):
    name = 'myapp.subapp1'
    label = 'myapp.subapp1'

а затем в myapp/subapp1/__init__.py

default_app_config = 'myapp.subapp1.apps.SubApp1Config'

Сделайте то же самое для «myapp/subapp2» и закомментируйте «myapp.app2» из INSTALLED_APPS.

Затем я могу успешно запустить ./manage.py makemigrations myapp.subapp1.

Однако, если я затем раскомментирую myapp.subapp2 из INSTALLED_APPS

и измените myapp/subapp2/models.py так, чтобы он выглядел так:

class Baz(models.Model):
    bar = models.ForeignKey('myapp.subapp1.Bar')

а затем запустите ./manage.py makemigrations myapp.subapp2 я получаю:

SystemCheckError: System check identified some issues:

ERRORS:
myapp.subapp2.Baz.bar: (fields.E300) Field defines a relation with model 'myapp.subapp1.Bar', which is either not installed, or is abstract.

Как я должен описать отношение внешнего ключа между myapp.subapp2.Baz.bar и myapp.subapp1.Bar?

Заранее спасибо.


person ckot    schedule 24.03.2016    source источник


Ответы (1)


Я на самом деле понял это давно, но я полагаю, что не должен оставлять вопрос без ответа. Мне не пришлось использовать это — это было просто упражнение в том, чтобы сделать часть приложения необязательной. Наличие внешнего ключа между необязательными подприложениями было немного надуманным, я просто пытался понять, как на них ссылаться.

Оказалось, я просто запутался между app_label и тем, что вы вставили INSTALLED_APPS

В этом случае я бы просто установил app_labels на myapp_subapp1 и myapp_subapp2, однако в INSTALLED_APPS они будут установлены как myapp.subapp1 и myapp.subapp2.

При вводе ./manage.py showmigrations подприложения будут отображаться как myapp_subapp1 и myapp_subapp2, а не subapp1 и subapp2, что вызывало опасения, поскольку подприложение с настоящим именем может конфликтовать с чем-то другим. Например, мне не нравится, что django-mutant не использует пространство имен, это вклад, поэтому в итоге вы получаете app_labels, такие как web, text, которые могут полностью классифицироваться чем-то вместо mutant_web и т. д.

Затем при использовании внешних ключей на них будет ссылаться как myapp_subapp1.Bar вместо того, что я делал ранее как «myapp.subapp1.Bar».

person ckot    schedule 19.04.2016