All streams
Search
Write a publication
Pull to refresh
12
0
Александр Литвиненко @litvinenko1706

Пользователь

Send message

При чтении статьи могло сложиться неверное впечатление (см. комментарии вверху), что автор:


  • не любит Алхимию такой, какая она есть / считает её подход злом
  • не попытавшись понять философию Алхимии, полез её исправлять под привычный Active Record
  • любит магию и не любит писать явный код

Это не так, поэтому чуть подправил некоторые формулировки и добавил спойлер в конце статьи с обоснованием актуальности проделанной работы.


Спасибо!

Я люблю Алхимию именно за её гибкий интерфейс и явный SQL. В Алхимии можно гораздо больше, чем в любой Active Record ORM.


Но гибкость всегда выливается в более длинный код, и это нормально.
Хотелось иметь "ярлыки" к этому гибкому коду для самого простого CRUD-а или быстрых джоинов.
С ними можно простые задачи выполнять очень коротким кодом, имея возможность писать более гибко на обычной Алхимии.


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


Также см. подобные мысли в ответе выше.

1.


Как-то это… Не python-way совсем. Давайте оставим джангу в стороне. Алхимия в том виде, в каком она Вам
кажется неудобной на самом деле заставляет вас писать более очевидный и правильный код:

Я не говорю что подход Алхимии плохой. Я говорю, что мне простота кода была важнее, чем правильность. Для обычного создания объекта в контроллере в чистой Алхимии надо писать одни и те же 3 строки вместо одной, как в Active Record ORM. Алхимия напрягала в простых задачах, где не нужно 10 объектов добавить в сессию, а потом только один раз flush.


Мне подход Алхимии нравится именно отсутствием магии и контролируемостью кода. Но в простых задачах это неудобно, и я решил сделать Active Record поверх, а не вместо Data Mapper, как дополнительную плюшку, а не как основной вариант работы.


Я люблю SQLAlchemy такой, какая она есть. И именно от любви к ней я сделал её ещё удобнее (как минимум, для себя и коллег на работе).


2.


Кстати, а когда у Вас там commit будет? А flush?

При create, update, delete будет сразу flush. При надобности можно сделать настройку, чтоб бы не flush, а commit (ну или autoflush выставить)


3 .


А что если мне id нужен вставляемой сущности?

Вы его получите после flush-а, т.е. после


user = User.create(...)

вы имеете user.id

это скорее вопрос к проектировке безопасности приложения.


конечно, не следует разрешать фронтенду передавать что угодно в качестве фильтра.

можно. но каждый раз придётся писать новый алгоритм.
я же, как и создатели Django ORM, решил иметь возможность описать нужные джоины декларативно и дать протестированному коду это джоины сделать.


Это — не серебряная пуля, здесь есть свои минусы. Однако это удобная дополнительная фишка, которая может сделать код короче.

1. Тут вопрос стиля и личных предпочтений. Вы привыкли к одному, я — к другому.
Я не против стандартного синтаксиса Алхимии, просто в некоторых местах мне он неудобен. А в других местах, напротив, Алхимия очень рулит.


2.


Я не очень понимаю чем вам такой синтаксис не удобен?:
.options(
joinedload_all(Watchdog.recipe, Recipe.recipeset, RecipeSet.job),
joinedload_all(Watchdog.recipe, Recipe.recipeset, RecipeSet.lab_controller),
joinedload_all(Watchdog.recipetask, RecipeTask.task)
)

лично мне не видно иерархии.


3. С Алхимией работаю год. И за этот год после Active Record наболело очень многое. Что и вылилось с описанный пакет.

Да, в таком подходе есть минусы. Ещё минус, что в таких "магических строках" легко ошибиться и, допустим, вместо user___name, написать yser___name, IDE такое не провалидирует, и получим ошибку в runtime.


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


А по поводу злодейской "тяжёлой комбинации" и вообще валидации: на боевом проекте мы валидируем такие магические строки, приходящие с UI (с помощью marshmallow)


Имею в планах сделать возможность валидации таких строк.

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


filters = {'rating__in': [2, 3, 4], 'body__like': '%search%'} # пришло с фронтенда
Post.where(*filters).all()

Придется писать ручками:


session.query(Post).filter(Post.rating.in_([2,3,4]), Post.body.like('%search%')).all()

тут дело именно в том, что нельзя задать фильтр/сортировку, передав строку


filters = {'rating__in': [2, 3, 4], 'body__like': '%post%'}
Спасибо, буду знать!

Information

Rating
Does not participate
Location
Харьков, Харьковская обл., Украина
Registered
Activity