LINUX.ORG.RU

Философия Django

 , ,


0

3

Привет!

Надоело просто так скучать на изоляции, решил изучить Django.
Что с самого начала бросается в глаза - везде строки и динамические атрибуты. Почему так? Это же неудобно ни разу

from django.contrib import admin
from . models import Bb

class BbAdmin(admin.ModelAdmin):
    list_display = ('title', 'content', 'price', 'published')
    list_display_links = ('title', 'content')
    search_fields = ('title', 'content')
А можно было бы:
class BbAdmin(admin.ModelAdmin):
    list_display = (Bb.title, Bb.content, Bb.price, Bb.published)
...

Другой пример:
mm = MainModel.objects.get(pk=1)
another = mm.linked_set.filter(pubdate_lt=date)

Почему не:
mm = MainModel.objects.get(pk=1)
another = mm.set(Linked).filter(lt(Linked.pubdate, date)

Или вот ещё, банальные url'ы:
urlpatterns = [
    path('polls/', include('polls.urls')),
]

Заменить на:
from . polls import urls as purls
urlpatterns = [
    path('polls/', include(purls)),
]

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

Или я не понимаю что-то?

★★★★★

Ответ на: комментарий от eternal_sorrow

её там нет

Ну ладно уж! Достаточно популярный и хороший фреймворк, должны были сделать не просто от балды.

ls-h ★★★★★
() автор топика
Последнее исправление: ls-h (всего исправлений: 1)
Ответ на: комментарий от ls-h

должны были

Кому должны?

Ну и да, когда создавались большинство из этих вещей, вряд ли django был таким популярным. И вряд ли кто то тогда думал о какой то философии, делали как казалось проще.

Многие вещи из тех, что ты тут предлагаешь, реализованы в других фреймворках. А джанго старичок и в нём многие вещи сделаны не так красиво, как хотелось бы. Но тем не менее это работает.

eternal_sorrow ★★★★★
()

Если всё всюду импортить, можно доимпортиться до циркулярных импортов, что не есть хорошо.

Или же предполагается что разные части проекта могут жить достаточно разрозненно, так, что одно из другого импортировать будет проблематично (джанговская концепция app).

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

Да и в конце концов в питоне разница между строкой и идентификатором скорее культурная чем концептуальная. IDE с плагинами под джангу и так все эти строки понимают.

PolarFox ★★★★★
()

Надоело просто так скучать на изоляции, решил изучить Django

Взоржал. ЛОР — это такой юмористический ресурс, а самые смешные шутки в категории Web-development.

Это же днище унылое, для формошлёпства созданное. Одумайся.

Ты просто ошибся, или действительно не нашел ничего интересней?

WitcherGeralt ★★
()
Ответ на: комментарий от ls-h

Ну например, sqlalchemy orm работает примерно так как ты предлагаешь. А в django orm очень специфичный. Но к нему можно привыкнуть.

eternal_sorrow ★★★★★
()
Последнее исправление: eternal_sorrow (всего исправлений: 1)

Ну вообще например у джанго есть философия слабой связанности. Из за этого импорты напрямую из одного модуля в другой не всегда приветствуются.

class BbAdmin(admin.ModelAdmin):
    list_display = (Bb.title, Bb.content, Bb.price, Bb.published)

Ну тут можно объяснить так: мы один раз уже указали , какая модель используется у нас в ModelAdmin, повторять это ещё 50 раз в Bb.title, Bb.content, Bb.price, Bb.published - семантическая избыточность. А что если мы укажем поле не из Bb а из другой модели? Ошибка? А IDE тебе эту ошибку подскажет? Так в чём разница?

eternal_sorrow ★★★★★
()
Последнее исправление: eternal_sorrow (всего исправлений: 2)
Ответ на: комментарий от anonymous

Flask-restless.

Но я же не о том, что джанга свою работу не выполняет. Я говорю, что формошлёпие по-опделению не может быть интересным.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Ты просто ошибся

Мне нравится Python. Я погуглил, какие вакансии есть с ним связанные. Выяснилось, что Django достаточно востребованная вещь. А что лучше в качестве фреймворка?

ls-h ★★★★★
() автор топика
Ответ на: комментарий от eternal_sorrow

А что если мы укажем поле не из Bb а из другой модели? Ошибка?

А что если класс унаследовать от чего-то другого? Это ошибка уже совсем другого рода, это не опечатки. Строка-то тут всё равно не лучше. И кроме поиска ошибок есть другие важные и полезные вещи: быстро найти места использования сущности, переименовать во всех местах и т.п.

ls-h ★★★★★
() автор топика

Ты пытаешься найти красивую архитектуру там, где ее нет. В Django даже Entity по сути нет, а модель «умная» - что позволяет гонять ее по всем слоям приложения и вызывать методы сохранения/изменения/удаления вообще в любом месте приложения. Это ж полный треш вообще. Слоя сервисов вообще нет: просто берешь и делаешь запрос к базе где угодно. Когда я впервые попробовал пилить на Django, мне понравилось, потому что получается очень быстро, ничего настраивать не надо - все из коробки, как говорится. Но потом я понял, какой это ад. Django позволяет пилить приложения очень быстро - и иметь готовую админку сразу. Но если говорить о какой-то красивой архитектуре, то это не про Django.

Если говорить о других фреймворках, то вообще затрудняюсь сказать, есть ли фреймворки для Питона с хорошей архитектурой. Ну, скажем, аналог NestJS в Питоне я не вижу.

dimuska139 ★★
()
Ответ на: комментарий от ls-h

Зависит от цели. Если что-нибудь быстро наформошлёпить, то джанга вне конкуренции. Если погибче, то тоже просто, хорошо и проверено временем, то Flask.

А если современное Web API с претензией на производительность, то aiohttp, FastAPI, мб Sanic.

WitcherGeralt ★★
()
Ответ на: комментарий от ls-h

Flask - микрофреймворк. Ты можешь подключить к нему любую ORM, какую хочешь. Например, sqlalchemy.

dimuska139 ★★
()
Ответ на: комментарий от WitcherGeralt

На aiohttp вообще реально написать API качественно? Понятно, что от квалификации разраба зависит, но это ж просто либа, не фреймворк - там же вообще никакой структуры даже минимальной не предоставляется - пили как хочешь.

dimuska139 ★★
()
Ответ на: комментарий от dimuska139

Ну, скажем, аналог NestJS

Спасибо. Правда лучше ссылки на какие-нибудь небольшие примеры красивого кода.

ls-h ★★★★★
() автор топика
Ответ на: комментарий от ls-h

Про пирамиду (ископаемое нинужно) ничего не знаю, а фласк очень хорошо дружит с алхимией. Алхимия — эталон ORM, если лучше что-то и есть, то я об этом не знаю.

Про flask-restless я уже упоминал, это вообще атогенерит (без кодогенерации) апишку на основе моделей.

WitcherGeralt ★★
()
Ответ на: комментарий от ls-h

Как на них выглядят подобные ORM штуки?

И там, и там предполагается что скорее всего прикрутишь sqlalchemy.

PolarFox ★★★★★
()
Ответ на: комментарий от dimuska139

Ничто же не мешает.

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

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от dimuska139

Рецепты, как правило, покрывают конкретный кейс, и запилены конкретным разрабом по своему вкусу. Вся соль использования микрофреймворка в том, что можно сделать всё по-своему под свой собственный кейс.

А в плане фич aiohttp от фласка ничем в сущности не отличается.

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Я в том комменте не совсем правильно выразился насчет запросов в базу. Сами сервисы в базу не ходят, а взаимодействуют с ней через слой репозиториев. Слой сервисов - это слой бизнес-логики, в моем понимании, не зависящий от конкретного фреймворка. То есть, грубо говоря, то, что вызывается из контроллеров и то, что дергает методы репозиториев для работы с хранилищем. В репозиториях скрыта логика взаимодействия с хранилищем. Сервис ничего о хранилище не знает. Откуда пошла терминология такая, точно не знаю, но, думаю, из Java Spring.

dimuska139 ★★
()
Ответ на: комментарий от WitcherGeralt

Ясно. Да, согласен. Сам юзаю микрофреймворк, правда пхпшный)))

Сервисы мы все знаем что такое (демон). Это не оно.

Не, я про архитектурный слой внутри приложения. Конечно, это не демон.

dimuska139 ★★
()
Ответ на: комментарий от dimuska139

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

WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Мне такая архитектура (личное мнение) кажется просто наиболее удобной и красивой, но на Java я не пишу. Примерно по такому принципу, кстати, сделан фреймворк Symfony.

dimuska139 ★★
()
Ответ на: комментарий от dimuska139

Имхо, для среднего проекта это неоправданно большое количество абстракций.

У меня кореш пишет проект на спринге небольшой командой. Оно прибыльно, но фич там всего-ничего. Кода при этом за сотню тысяч строк переваливает.

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

WitcherGeralt ★★
()

А вообще для питона рекомендую стек BDSM:

bottle.py — отличный wsgi-микрофреймворк, имеет свой собственный движок шаблонов, позволяющий раскрыть полный функционал питона прямо не выходя за пределы шаблона.

dataset — библиотека, позволяющая сохранить ваши данные в целости и сохранности. Зачем тратить время на создание моделей, кому вообще нужны миграции? Лучшего сочетания простоты nosql и надёжности sql просто не найти. Удобнее — только питоновский словарь.

scrapy — лучшее средство для асинхронного доступа к API сторонних сервисов, даже если этот API не очень очевиден.

MS SQL или MySQL по вкусу. Тут можно без долгих объяснений. Лучшие базы данных проверенные временем.

PolarFox ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Не знаю конкретно про Spring, но вообще такое разделение на слои абстракции очень удобно.

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

Repository - абстракция для хранения данных. И все запросы в базу только там. Нужна работа с другой СУБД - делаешь новый Repository, реализующий тот же интерфейс, но уже с кодом для работы с другой СУБД.

Service Layer - все ясно, уже писал выше.

Удобно тут то, что я могу без проблем покрыть юнитами, скажем, Service Layer. То есть я пихну туда Mock-объект репозитория и все - и не надо мокать ORM-ку. Если я захочу покрыть тестами контроллеры, то пихну туда Mock-объекты нужных мне сервисов, и не придется мокать какие-то внезапные запросы в базу и т.п. Потому что контроллеры взаимодействуют только с сервисным слоем.

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

dimuska139 ★★
()
Последнее исправление: dimuska139 (всего исправлений: 2)
Ответ на: комментарий от dimuska139

Нужна работа с другой СУБД - делаешь новый Repositor

Это же байка. БД просто так никто не меняет, а когда меняет (например классическую реляционную на какую-нибудь аналитическую), это скорее всего отражается на архитектуре приложения в целом. Мокать БД, спасибо докеру, больше не нужно, поднял настоящую при тесте, наколотил фикстуры, и вот у тебя всё по-правде, а не моки, которые тоже могут быть кривыми.

Service Layer - все ясно, уже писал выше

Выносить код в библиотеку в принципе правильно вне зависимости от архитектуры. Но я в упор не понимаю на кой это обосабливать в отдельный слой абстракции.

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

WitcherGeralt ★★
()

Я конечно мимокрокодил, но например в пыхе такая же история. Сделано для того, чтобы раньше времени не загружать то, что возможно будет не нужно. Вероятно что тут то же самое, такая вот «ленивость».

no-such-file ★★★★★
()
Последнее исправление: no-such-file (всего исправлений: 1)
Ответ на: комментарий от ls-h

Это путь в никуда. Занимаясь разработкой на джанго вы не являетесь программистом в прямом понимании этого слова.

Andreezy
()
Ответ на: комментарий от dimuska139

Ну, для Flask дофига «рецептов», дополнительных пакетов и примеров в том же Github. Про Aiohttp такое сложно сказать.

А что там вообще может быть непонятного? Отличная понятная дока

Andreezy
()
Ответ на: комментарий от Andreezy

Это путь в никуда. Занимаясь разработкой на джанго вы не являетесь программистом в прямом понимании этого слова.

Спорное заявление. Зависит от многих факторов. Ни что не мешает, используя максимально упрощающий веб-рутину веб-фреймворк, писать сложную бизнес-логику, в которой хоть всю книгу Кормена по алгоритмам использовать, если прикладная задача этого требует.

OSBuster
()
Ответ на: комментарий от WitcherGeralt

Flask-restless

А можно вкратце, что лучше, это или flask-restx? :)

на голом фласке получались красивейшие апишки

Или может лучше вообще без этих extension-ов?

У меня API простой будет.

the1 ★★
()
Последнее исправление: the1 (всего исправлений: 1)
Ответ на: комментарий от OSBuster

Спорное заявление.

Зато очень хорошо помогает детектить ЯПЕШУТОЛЬКОНАВСЕОСАТЛЬНЫЕЛОХИ-говнокодеров.

oldstable
()
Ответ на: комментарий от dimuska139

Нужна работа с другой СУБД - делаешь новый Repository, реализующий тот же интерфейс, но уже с кодом для работы с другой СУБД.

В ActiveRecord с этим больших проблем тоже нет, так-то, код для работы с разными СУБД инкапсулируется либо в записях, либо в самой ORM. А вообще один фиг, у всех приложений на AR-ORM со временем появляется промежуточный уровень с бизнес-логикой между ORM и контроллерами.

oldstable
()
Ответ на: комментарий от the1

Это же не пересекающиеся вещи.

Flask-restless нужен только для того, чтобы быстро сгенерировать CRUD для уже описанных моделей. Для полноценного API он не годится, но может использоваться вспомогательно. Для прототипирования в самый раз.

Зачем нужен flask-restx для меня секрет. Если бы стоял такой выбор, я бы лучше взял голый фласк. Но вообще, синхронщину брать бы не стал.

WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

Так всё равно получается AR-ORM + обвязка для кидания JSON’чиков по REST’у.

oldstable
()
Ответ на: комментарий от oldstable

В ActiveRecord с этим больших проблем тоже нет, так-то, код для работы с разными СУБД инкапсулируется либо в записях, либо в самой ORM.

Если речь идет о хранилищах, поддерживаемых этой конкретной ORM, то да. Но как быть, если потребуется другой тип хранилища? Данные могут вообще не в базе лежать.

Кроме того, минус Active Record в том, что модель содержит методы работы с хранилищем. Из-за этого невозможно сделать сервисный слой независимым от фреймворка - модель Active Record будет проходить через все слои приложения. Модель в Active Record не просто класс, а прямая зависимость от конкретного фреймворка.

Ну и вообще Active Record сильно развязывает руки, позволяя разработчикам вызывать методы работы с базой где угодно в коде. Я уж молчу про то, что если требуется поменять одну библиотеку с Active Record на другую, то придется очень много чего менять. И эти изменения коснутся не только слоя репозиториев.

dimuska139 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.