models.py стає величезним, який найкращий спосіб розбити його?


91

Вказівки від мого керівника: "Я хочу уникати введення будь-якої логіки в models.py. Відтепер давайте використовуватимемо це як лише класи для доступу до бази даних, а всю логіку зберігатимемо у зовнішніх класах, які використовують класи моделей, або обертаємо їх".

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

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

Отже, чи існує простий спосіб видалення класів моделей із файлу models.py, але все-таки моделі працюють з усіма інструментами Django? Або є зовсім інше, але елегантне рішення загальної проблеми "великого" файлу models.py? Будь-який внесок буде вдячний.


7
Ви знаєте заяву про імпорт, так?
balpha

7
PS. Я не маю на увазі це образливо, я просто хочу знати, де ти знаходишся.
balpha

1
Так, але я не знав, чи будуть адміністративні інструменти django працювати, просто використовуючи оператори імпорту для втягування моделей. Я б скоріше запитав тут, ніж витратив багато часу на випробування з використанням простого імпортування оле, щоб лише виявити, що інструменти django погано з ними грають. Я визнаю, що я новачок у python та django, тому, мабуть, я лише просто розумію імпортну заяву ...
Eddified

Відповіді:


64

Django розроблений, щоб дозволити вам створювати багато малих програм замість однієї великої програми.

Усередині кожного великого додатку є безліч дрібних додатків, які намагаються бути безкоштовними.

Якщо ваші models.pyпочуття великі, ви робите занадто багато. Стій. Розслабтесь. Розкласти.

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

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

У нас близько десятка додатків, кожна model.py- не більше 400 рядків коду. Усі вони досить зосереджені на менш ніж півдюжині дискретних визначень класів. (Це не жорсткі обмеження, це спостереження щодо нашого коду.)

Ми розкладаємося рано і часто.


1
прямо в точці. будь-який нетривіальний веб-додаток буде декількома невеликими "програмами". взяти натяк на внесок та інші популярні програми, автентифікація користувача - це одна програма, додавання тегів - інша, профілі користувачів - ще одна тощо.
Хав'єр

4
Хоча це "правильний" шлях і корисно знати, це не зовсім те, що я шукав. Я перепрошую, якщо не було можливості дізнатись, яку саме відповідь я шукав. :)
Видано

@Eddified: якщо ви цього не зробите, це буде лише погіршуватися. Почніть розділяти зараз.
S.Lott

Досить смішно, саме в цей момент я слухаю Джейкоба Каплана Мосса (в OSCON), який саме і дуже детально пояснює це ;-).
Алекс Мартеллі,

13
Відповідь Глена Мейнарда набагато краща. Поділ складного веб-додатка на багато додатків, безумовно, є гарною практикою, але так само як і рефакторинг файлу model.py ВНУТРИ програми. Ці дві дії можуть бути ортогональними.
Ерік,

108

Для класів моделей природно містити методи, що впливають на модель. Якщо у мене є модель 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

так що я все ще можу написати "з site.models імпорту книги".


Далі потрібно лише для версій до Django 1.7, див. Https://code.djangoproject.com/ticket/3591

Єдина хитрість полягає в тому, що вам потрібно явно встановити додаток кожної моделі через помилку в Django: вона передбачає, що назва програми є третьою до останньої записи в шляху до моделі. "site.models.Book" призводить до "site", що правильно; "site.models.book.Book" змушує думати, що назва програми - "моделі". Це досить неприємний хак з боку Джанго; Ймовірно, він повинен шукати у списку встановлених програм відповідність префіксу.

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

Можливо, ви могли б використати базовий клас або метаклас для узагальнення цього, але я ще не заморочувався цим.


2
+1 Я використав це з успіхом. Хоча С. Лотт має рацію в декількох додатках, і це гарна ідея, це рішення тут і зараз.
Олександр Люнгберг,

35
Я не бачу великої вигоди, якщо розділити речі на купу додатків, коли ваші моделі тісно пов’язані між собою.
Гленн Мейнард,

2
Це мене цікавить. Я прочитав опубліковане посилання на вікі-посилання django і виявив таке: "Перевірено, що він працює без мета-класу app_labels у поточній головній гілці." То чи це означає, що якщо ви працюєте з основною гілкою, ми можемо відкинути матеріали Meta: app_label? Це бентежить, оскільки після коментаря щодо квитка вирішує цю проблему.
Dan.StackOverflow

2
Я щойно тестував з багажником (станом на раніше сьогодні, r11286); якщо ім'я_програми не встановлено, модель просто не відображається в "sqlall appname" і, ймовірно, не буде створена syncdb (але я не використовую це, тому я не можу його перевірити). Це досить заплутаний випадок помилок, оскільки він не викликає жодних помилок; воно просто мовчки не з’являється.
Glenn Maynard

2
Нічого собі, майже через 10 років, і я все ще люблю це рішення. Погодився, що це набагато кращий підхід, ніж розбиття коду на менші програми, що, на мій погляд, може призвести до кодової бази, про яку важко міркувати.
Майкл Хейс

5

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

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

    Помістіть їх в окремі файли. Якщо є залежності, використовуйте імпорт, щоб втягнути додаткові моделі.

  • сторонні функції логіки / корисності в models.py

    Помістіть додаткову логіку в окремі файли.

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

    Створіть новий диспетчер в окремому файлі.

  • методи, очевидно пов'язані з моделлю

    save, __unicode__ та get_absolute_url - приклади.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.