Комментарии 62
на мой взгляд бизнес-логика это как раз такая логика, которая работает с данными и соответственно должна быть рядом с ними
а вид должны отвечать за обработку входных параметров, возможно обработку ошибок, подготовку результатов к выводу и тд
Размещая БЛ во view вы сами себя лишаете возможности повторно использовать свой же код. Сильно толстые модели тоже плохо, но никто не запрещает делать "бизнес-прослойку" между view и models
Так Вы приходите к тому, что БД выступает только как умное хранилище, а всю логику переносите во вьюхи. Противоположный случай — максимальное количество логики в модели, если отойти от джанги — то на вьюхах, процедурах и триггерах СУБД, так приходим к двухзвенной архитектуре. В случае трехзвенной архитектуры, в моделях описываем логику хранения и отображения данных, во View — взаимодействие с клиентом
Однако очень часто я пропускаю тот момент когда она сильно разрастается, а переписывать уже некогда…
Разбивайте на submodules:
https://stackoverflow.com/questions/6336664/split-models-py-into-several-files
И views также можно разбить. Хотя лучше конечно новый app и туда часть перенести.
Дизайн в шаблонах (templates)
— то что в стандартной MVC модели называют «Controller» в Django называют «views»
— а то что в стандартной MVC модели «View» в Django называют «templates».
Как именно предлагаете тестировать логику в видах? Юнит-тесты станут невозможны и нужно будет писать уйму интеграционных, да?
Мне одному не нравятся Class-based Views? Неохота доказывать/объяснять почему (слишком субъективно), просто интересно, есть ли ещё такие
В документации так и написано:
Class-based views provide an alternative way to implement views as Python objects instead of functions.
Этот способ не лучше и не хуже, он просто другой. И да, вы не один))
Но вообще посмотрите на дату публикации — вполне себе веселое пятничное чтиво.
Меня вот начало веселить прямо с «ошибки» №1.
Если вам пришлось переопределять большинство методов − вы, скорее всего, наследуетесь не от того класса.
Работал над большими и маленькими проектами. Ни разу с проблемами не сталкивался. Ну, кроме того, что некоторые разработчики излишне ретиво создают миксины, и потом наследуются от 20 миксинов, которые делают кучу лишней работы. Но это просто проблема с конкретными разработчиками, а не CBV в принципе.
Так они позволяют очень легко и наглядно переиспользовать код. На их основе, например, сделал недавно систему, которая генерирует HTML, PDF и Excel отчеты. Повторяющегося кода нет вообще благодаря CBV. Все детали конкретного формата обрабатываются миксинами.
А что тогда вы скажите про forms в Django?
Чтобы не было слишком много миксинов, нужно базовые CBV делать достаточно мощными. Может быть в них будет несколько редко используемых методов, но этот компромисс лучше чем попытка загнать абсолютно все в миксины.
Использую и CBV и миксины для них, за счет того что базовые CBV большие и многофункциональные, миксинов немного, чаще используется обычное наследование с переопределением нескольких методов:
https://github.com/Dmitri-Sintsov/django-jinja-knockout/tree/master/django_jinja_knockout/views
А из оставшихся еще 30% очевидным образом не работают, демо проектов не имеют(или пункт 1) и как его использовать непонятно.
Неправда. Я работаю много лет над двумя очень большими и посещаемыми проектами, и двумя поменьше. В каждом размер requirements.txt
от 40 до 100+ строк.
Существует масса отличных поддерживаемых пакетов. Бывает, что разработчики не успевают за версиями Django (причем не всегда при этом совместимость ломается, например, последний переход 1.10-1.11 практически безболезненный), тогда достаточно на GitHub поискать обновленный форк, чаще всего он находится. Если не находится, как правило, очень быстро можно допилить свой. И создать pull request.
А вот те, кто пишут велосипеды. Ребята, за вами очень тяжело поддерживать код. В отличие от готовых пакетов с PyPI/GitHub, у вас нет ни документации, ни примеров, ни комментариев, ни архитектуры.
Да и в большинстве случаев велосипедостроение возникает от незнания и неумения искать на djangopackages, pypi, github и просто google.
Я как раз с обычными проектами почти и не сталкиваюсь. Тем не менее, нахожу массу библиотек, которые облегчают мне работу. Другое дело, что совсем тривиальный функционал в проект стараюсь не тащить. Например, в статье приводятся какие-то модули, реализующие тривиальную функциональность.
А так существует масса полезных батареек для Django. Например:
- django-allauth
- django-localflavor
- django-braces
- django-crispy-forms
- django-taggit
- django-extensions
- django-select2
Ну и наверное много чего еще не вспомнил. Я видел попытки вместо использования данных (и других) модулей написать свой код. Но ни разу не видел, чтобы получилось лучше.
Недавно видел проект, где неопытный (мягко говоря) автор нагородил систему полиморфных моделей. в Django. Во-первых, они там были совершенно не нужны. Во-вторых, код был недокументирован, крайне уродлив и непонятен. В-третьих, он ломался от каждого чиха. Думаю, при любой смене версии Django поддержка этого чуда попьет крови у тех, кто вынужден будет поддерживать это поделие.
Ну и по-моему опыту так получается почти всегда. В другом проекте написан свой модуль для работы с ElasticSearch. Абсолютно непонятный, кривой, и с ужасной производительностью. Но на него теперь завязано почти все, и переписать нормально нет возможности. :(
Короче, я очень сильно не люблю велосипеды. В моей практике в основном получалось, что код с велосипедами ужасен, а код, где авторы старались использовать доступные модули — чистый и легко поддерживаемый.
А я до сих пор не могу понять зачем использовать Django как ORM + DRF без inline formsets, admin и прочего что так ценно в Django. Если нужно только серверное API для клиента на react / angular, не лучше ли использовать на сервере node.js?
Я использую AJAX в своих модулях (у меня knockout.js) но подход смешанный — часть кода обычный серверный html, часть AJAX виджеты. Не SPA. Мне кажется что для SPA лучше next.js или что-то подобное.
Да, admin в Django очень хороший, не спорю. Только это классическое приложение не REST и не AJAX. node.js позволяет использовать один язык на серверной стороне и клиентской, в случае AJAX / REST должно быть достаточно.
inline formsets вообще одна из самых ценных фич Django, автоматический маппинг отношений один ко многим с уровня моделей на уровень форм. Вроде бы что-то похожее появилось в последних версиях Angular, массивы форм: https://angular.io/docs/ts/latest/api/forms/index/FormArray-class.html
Поддержка множественных форм с отношениями до сих пор большая редкость во фреймворках.
Я не хочу начинать языковой холивар, но мне кажется, что Javascript — плохой язык. Это костыль, который по роковому стечению обстоятельств зажил полноценной жизнью. А вся экосистема Javascript/Node.js — это какой-то сумасшедший калейдоскоп, где каждый день с утра уже надо переписывать проект, потому что поменялись все версии библиотек, поменялась парадигма, поменялась система сборки проекта. Чтобы в этом непрерывно меняющемся зоопарке библиотек и инструментов разбираться… Нет, я уж лучше что-нибудь другое изучу.
Мне тоже Питон больше нравится. Только браузеры его не понимают, поэтому от Javascript все равно никуда не деться в веб-программировании.
Надеюсь, WebAssembly и подобные проекты наконец-то переломят ситуацию. Когда появилась Mozilla, было несколько более-менее успешных попыток внедрить поддержку других языков (в частности, Python и Tcl/Tk). Были даже весьма интересные расширения на этих языках. К сожалению, все это не взлетело… Возможно потому что в то время, не было реальной необходимости в полноценном языке программирования в браузере. Сейчас ситуация другая, и, сильно надеюсь, что Javascript наконец с почестями похоронят. На мой взгляд, это такой PHP для frontend'а.
Судя по тому что в Javascript (как и в PHP) добавляют все больше фич из Python, в том числе генераторы и variadic args, у них планы совсем другие.
Особенно преуспевают разработчики PHP, они вообще похоже изучают PEP и детали CPython. Только при этом основа языка остается кривой: из-за совместимости не поправить.
Ну а в Javascript так и нет нормального наследования, по сравнению с Python особенно бросается в глаза. Нет автоматических нормальных миксинов, нет нормальных метаклассов. Делают extend и миксины вручную, это конечно работает но уступает по изяществу нормальному множественному наследованию в Python.
Конечно, статья немного субъективна, но думать в любом случае никто не запрещал. Перед началом проекта сядь и подумай — вообще подойдет тебе джанга или будет только камнем?
У меня для многих проектов изначально не было смысла делать веб-интерфейс и я велосипедил с простых скриптов, слегка связанных общими модулями. Для простых одностраничных веб-приложений добавлял Flask. Но потом внезапно понял что структуру проекта я пытаюсь выдерживать в django-стиле, мне не хватает удобных settings, и волшебного django ORM с его моделями.
С недавних пор я по-умолчанию начинаю проект с django-темплейта, выпиливая веб-часть, если не нужна.
Что касается логики во View — достаточно один раз (ок, два — точно достаточно для большинства чтобы осознать) столкнуться с тем, что, внезапно, логика начинает использоваться не только с фронтенда, а еще и с бэкенда (например, из celery-тасков создание или обработка сложных объектов). После этого количество кода логики во view резко уменьшается и появляются либо контроллеры, либо распухают модели, либо появляются отдельные под-приложения, которые могут вызываться откуда угодно.
Надо понимать что View (как бы кто ни говорил о том что в django это модифицированный Controller) предназначена, в первую очередь, для реализации схемы request-response и использовать ее с другой целью — смысла мало.
Люди, которые не любят CBV и используют функции для вьюшек — я вам откровенно и честно завидую! У вас, наверное, достаточно времени на качественный рефакторинг и требования изначально четкие и не меняются.
В противном случае я не представляю как можно не переиспользовать код в сложном проекте.
Конечно, стандартные классы вьюшек — простейшие и даже для ListView приходится переопределять много методов чтобы сделать то, что нужно. Но это в любом фреймворке так. Для простого прототипа достаточно django admin, но упаси Нортон строить дальше логику на нем!
Вот, кстати, я бы добавил 11ю ошибку — «использование django admin для построения интерфейса приложения». Можно сколько угодно обклеивать холодильник пенопластом, но море он не переплывет, и хорошо если затонет рядом с берегом, а не на полпути (обратно грести дольше).
Конечно, если у вас предполагается NoSQL, высокие нагрузки или очень динамическая структура базы — то вам надо обязательно 7 раз задуматься и не торопиться с выбором. Но и в эту статью тогда не надо идти с комментариями типа «фу».
Люди, которые не любят CBV и используют функции для вьюшек — я вам откровенно и честно завидую! У вас, наверное, достаточно времени на качественный рефакторинг и требования изначально четкие и не меняются.
Конечно, стандартные классы вьюшек — простейшие и даже для ListView приходится переопределять много методов чтобы сделать то, что нужно. Но это в любом фреймворке так.
Простите, но вы сами себе противоречите. Для меня CBV — отвратительное решение, которого лучше бы не было совсем, чтобы молодые специалисты не забивали себе голову. CBV в Django — это как ООП в Java (ООП ради ООП). Нет никакого смысла в этих ваших классах, когда для страницы, чуть более сложной чем My Personal Home Page нужно переопределить с пяток методов, зарыться в родительские классы или писать новые миксины.
Да, миксины удобно, но не применимо IRL, к сожалению. Намного красивее и лаконичнее выглядят вью-декораторы. А когда у логика зависит от юзер-инпута — вообще пиши «пропало», CBV превращается в гомункула созданного Виктором Франкенштейном.
Я уже не говорю, про абсолютно блевотную контрукцию
url(r'^register/$', FormView.as_view(form_class=Register, success_url='/thanks/')
Не могу говорить за остальных, но я люблю python в первую очередь за красоту и лаконичность кода. И вот то, что выше абсолютно не эстетично.
Но дело в том, что при создании *любого* фреймворка авторы вынуждены, по определению, идти на поводу у универсальности подхода. Именно из-за этого и появляются конструкции типа CBV в Django, а также примеры кода, который может раздражать вас, меня или кого-нибудь еще внешней громоздкостью.
Я не сомневаюсь что вам, как и любому другому Python-разработчику, приходилось вынужденно залезать в исходники библиотек (django) для того, чтобы отладить что-то. Вы наверняка видели какое количество кода скрыто внутри и для обработки каких ситуаций оно предназначено.
Не все вещи можно удобно использовать с декораторами, иногда ООП-подход очень спасает.
К примеру, у меня есть проект, на котором создаются сложные отчеты. Десяток отчетов с разной логикой, но у всех есть экспорт в разные форматы, рисование графиков, а также куча похожих фильтров. Клиенту очень нужна кастомизация каждого поля, поэтому каждое значение буквально можно по-разному вывести.
Для меня решением стало написание общего класса с основной базовой логикой и дочерних классов со специфичными вычислениями. Наверное можно было все вынести в функции, но инкапсуляция, наследование и полиморфизм — не просто ненужные слова, они реально могут облегчить разработку и код станет более читаемым, когда параметры сгруппированы.
ООП в Java — это для перфекционистов, но даже там подход по-своему красив (я не оч люблю Java если что).
Опять же, я понимаю почему это было сделано и это достаточно элегантная попытка отделить взаимодействие разных частей кода (или библиотек).
Но вот как раз сигналы, на мой взгляд, совершенно не логичная именно для Python идеология.
А что тогда использовать вместо сигналов? Если всё ещё хотеть отделить взаимодействие разных частей кода.
Сигналы нужны для взаимодействия со сторонними библиотеками, когда в них встроится нельзя.
Вам понадобится перезапускать свой проект, используя python manage.py startapp, при каждом изменении шаблона.
startapp используется для создания нового приложения. При чем здесь перезапуск? Возможно вы хотели про runserver написать.
10 основных ошибок, совершаемых Django-разработчиками