Структурирование проекта Django с несколькими приложениями для минимизации зависимостей от импорта

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

Чтобы минимизировать эти зависимости, в настоящее время у меня есть 4 приложения:

  1. puzzles (contains all info about puzzles)
  2. users (all info about users)
  3. games (everything that relates to a user performing a puzzle)
  4. puzzle_explorer (generates new puzzles)

Однако меня интересует (например) количество пользователей, завершивших определенную головоломку, поэтому я сначала определил свойство nb_users_who_completed в модели puzzles.Puzzle... что приводит к двунаправленным зависимостям и потенциальным циклическим импортам

Поскольку в реальности, конечно, существует гораздо больше моделей, и гораздо больше кросс-прикладных свойств, быстрый и грязный способ не будет устойчивым. Сначала я думал о "расширении" различных моделей (плюс менеджеры) в пазлах с помощью Mixins:

#in games:
class Puzzle_Games_Mixin(object):
   @property:
   def nb_users_who_completed(self):
      return pass

   def custom_method1(self):
      pass

# in puzzles:
from games.mixins import Puzzle_Games_Mixin
class Puzzle(Puzzle_Games_Mixin, models.Model)

Это делает модульность более понятной, но не очень помогает в решении проблемы циркулярного импорта

Вторая стратегия, о которой я подумал, это расширить в games модель Puzzle с дополнительными кросс-прикладными функциями (как прокси-модели для использования тех же таблиц базы данных), и ссылаться внутри приложения games только на эти "локальные" прокси-модели:

# in puzzles:
class Puzzle(models.Model)

#in games:
from puzzles.models import Puzzle as original_Puzzle    
class Puzzle(original_Puzzle):
   class Meta:
       proxy= True # this model will not create new table & will refer to the database table of the parent model
   @property:
   def nb_users_who_completed(self):
      return pass

   def custom_method1(self):
      pass

Это очень хорошо, за исключением двух сложностей. Во-первых, я хочу включить в PuzzleAdmin информацию относительно пользовательских игр

Чтобы расширить change_view, я мог бы определить Inlines модели в играх, и подкласс PuzzleAdmin в играх, и снять с регистрации / зарегистрировать расширенную модель

Добавленная ценность заключается в том, что я также могу получить доступ к этим атрибутам в list_view

Однако у меня есть еще одно приложение puzzle_explorer, которое используется для создания пазлов в таблице базы данных puzzles_puzzle, и которое также зависит от приложения puzzles. puzzle_explorer приложение в основном добавляет Exploration модель

Конечно, приложение puzzle_explorer также добавляет некоторые функциональные возможности к модели Puzzle. puzzle_explorer полностью независим от games, поэтому вторая стратегия, примененная к обоим приложениям, работает нормально... за исключением административных целей

Я хотел бы расширить оба PuzzleAdmin list_view и change_view информацией об исследованиях, а также информацией об играх

Мой вопрос в том, что было бы лучшей практикой для реструктуризации проекта, чтобы позволить независимым модулям (здесь games и puzzle_explorer) добавлять дополнительную информацию в PuzzleAdmin без создания потенциальных циклических импортов?

Существует ли какой-либо "чистый" способ "инжектировать" новые функциональные возможности в модель и соответствующие ей ModelAdmin?

Вернуться на верх