models.py становится огромным, каков лучший способ разбить его? - PullRequest
84 голосов
/ 21 июля 2009

Направления от моего руководителя: «Я хочу избежать использования какой-либо логики в models.py. С этого момента давайте использовать это как только классы для доступа к базе данных и оставим всю логику во внешних классах, которые используют классы моделей, или перенесем их». *

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

Так есть ли простой способ использования включений? В PHP-языке я хотел бы предложить супервизору, что у нас просто есть models.py include () классов модели из других мест. Концептуально это позволило бы моделям иметь всю необходимую логику, но при этом уменьшить размер файла за счет увеличения количества файлов (что приводит к меньшему количеству проблем контроля версий, таких как конфликты и т. Д.).

Итак, есть ли простой способ удалить классы моделей из файла models.py, но все же работают ли модели со всеми инструментами Django? Или есть совершенно другое, но элегантное решение общей проблемы «большого» файла models.py? Любой вклад будет оценен.

Ответы [ 3 ]

100 голосов
/ 21 июля 2009

Для классов модели естественно содержать методы для работы с моделью. Если у меня есть модель Book с методом book.get_noun_count(), это то, к чему она относится - я не хочу писать «get_noun_count(book)», если только метод на самом деле не принадлежит другому пакету. (Это может быть - например, если у меня есть пакет для доступа к API Amazon с «get_amazon_product_id(book)».)

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

site/models/__init__.py
site/models/book.py

__init__.py выглядит так:

from .book import Book

так что я все еще могу написать "с сайта import.models Book".


Следующее требуется только для версий, предшествующих Django 1.7, см. https://code.djangoproject.com/ticket/3591

Единственная хитрость заключается в том, что вам необходимо явно установить приложение каждой модели из-за ошибки в Django: она предполагает, что имя приложения является третьей в последней записи в пути модели. «site.models.Book» приводит к «site», что является правильным; «site.models.book.Book» заставляет его думать, что имя приложения - «models». Это довольно неприятный хак со стороны Джанго; вероятно, он должен искать в списке установленных приложений совпадение префиксов.

class Book(models.Model):
    class Meta: app_label = "site"

Возможно, вы могли бы использовать базовый класс или метакласс для обобщения этого, но я еще не беспокоился об этом.

62 голосов
/ 21 июля 2009

Django позволяет создавать множество небольших приложений вместо одного большого.

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

Если ваш models.py чувствует себя большим, вы делаете слишком много. Стоп. Расслабьтесь. Раскладываем.

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

Рассмотрите пути обновления и разложите приложения, которые вы можете заменить когда-нибудь. Вам не нужно на самом деле заменить их, но вы можете рассматривать их как отдельный "модуль" программирования, который в будущем может быть заменен чем-то более прохладным.

У нас около десятка приложений, каждое model.py - это не более 400 строк кода. Все они довольно сосредоточены на менее чем полудюжине определений классов. (Это не жесткие ограничения, это наблюдения о нашем коде.)

Мы разлагаемся рано и часто.

4 голосов
/ 21 июля 2009

Я не могу понять, какая из многих возможных проблем у вас может быть. Вот несколько вариантов ответов:

  • несколько моделей в одном файле

    Поместите их в отдельные файлы. Если есть зависимости, используйте импорт, чтобы получить дополнительные модели.

  • посторонние логические / вспомогательные функции в models.py

    Поместите дополнительную логику в отдельные файлы.

  • статические методы выбора некоторых экземпляров модели из базы данных

    Создать новый Диспетчер в отдельном файле.

  • методы, явно связанные с моделью

    save, __unicode__ и get_absolute_url являются примерами.

...