LINUX.ORG.RU

Кто как использует python для создания API? Какая-то фигня получается...

 , , , ,


3

2

Добрый день.

Поймал себя на том, что при написании какого-либо веб-приложения принято:
1. Описать модель данных, в котором:
поле:тип
поле:тип
...
поле:тип
2. Эту модель замаршаллить специальным маршаллизатором по схеме, в которой
поле:тип
поле:тип
...
поле:тип
3. Эту модель для того, чтобы UI сделать, описать в любимом фреймворке, и там
поле:тип
поле:тип
...
поле:тип
4. Валидатор если писать, в нём тоже... Ну вы поняли.
Периодически натыкался на попытки интеграции всего этого, но слишком сложные. Что, так все и копипастят???

UPD. Всем спасибо, похоже, пора с фласка перелезать на DRF.

★★★★★

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

тебе джанга не нужна - это говно мамонта, все кто его пиарят - престарелые педерасты. и формы не нужеы. api - это api. оно отдает json. фронт делай на vue. из питоновских orm с валидацией mongoengine. почитай про jwt и graphql.

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

mongoengine

*facepalm*
«я старый солдат» и PostgreSQL во все поля, включая матстатистику.

Shadow ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Иногда (одно приложение из трехсот) лочат таблицами.

leave ★★★★★
()
Ответ на: комментарий от deep-purple

Ну, разве какой-нибудь bulk insert не лочит?

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

Решил сегодня поковыряться - вдруг проникнусь. Для примера, взял Gino, про который мне кто-то тут рассказал, и набросал следующее:

query = Book\
    .join(Author)\
    .select()\
    .where(Book.type == 'story')\
    .limit(chunk_size)\
    .offset(chunk_size * value)\
    .execution_options(loader=Book)

rows = await query.gino.load(
    Book.load(author=Author)
).all()

Как сделать так, чтобы при вводе rows[0]. IDE (Pycharm в моем случае) мне подсказала, какие поля есть в объекте Book? В том же php это решается с помощью PHPdoc, тут можно так же?

Причем, что забавно: могу написать rows[0].dsasd - и IDE даже желтым такое не выделяет. Причем поля dsasd у меня точно нет. Получается, если я случайно ошибусь и допущу опечатку, то получу ошибку во время выполнения?

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

Gino - это высер китайского п*дораса. Не трать время лучше. Раз захотел асинхронщины, то бери asyncpg либо извращайся ThreadPoolExecutor.

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

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

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

Я вот как раз раньше и пробовал asyncpg, но мне бы что-то более высокоуровневое, потому что руками писать мапперы результата запроса на объект - такое себе и «приятным» это занятие не назовешь.

Я вообще питон юзаю несколько лет периодически, но не сильно глубоко в него вникал, так скажем. Django знаю (фрилансил), Scrapy юзал, а сейчас надо написать небольшую консольную утилиту (взял Typer), которая асинхронно будет APIхи дергать и обновлять (и добавлять) данные в базе. Так что это не «захотел асинхронщины», а просто надо, чтобы граббер работал более-менее шустро.

Ну так вот чего-то в последнее время все больше в Питоне разочаровываюсь. Возможно, как-то не так его использую, но постоянно не покидает чувство какой-то ненадежности. Сплошная магия, куда ни плюнь. А IDE откровенные ошибки (как выше пример привел) даже не подчеркивает. Gino так вообще ад какой-то. Ну, это лично мое мнение.

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

Это ж жесть вообще. А чего-то типа PHPdoc нет, чтобы подсказать IDE, что в переменной лежать должно?

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

Тогда в чем удобство питона? Быстро наклепать, лишь бы работало? Код не надежный абсолютно получается. Рефакторить такое - игра в русскую рулетку. Если в php есть phpdoc, в js можно использовать тайпскрипт, то в питоне, получается, вообще нет способа хоть как-то обезопасить себя.

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

Почему? Я взял записи из таблицы с книгами, приджойнил к ним автора (у книги может быть только один автор) и замаппил на связанные объекты. Ну и limit-offset добавил, чтобы чанками читало. Это-то работает, другое дело, что IDE не знает, что у меня в переменной rows. В идеале (на мой взгляд) в строке rows[0].dsasd IDE должно красным подчеркивать dsasd и писать, что у Book нет такого свойства. Но, как я понял, я дофига хочу.

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

Выразительность высокая. Что-то быстро нахерачить — питон первый выбор.

Рефакторить такое - игра в русскую рулетку

Постоянно это повторяю, не далее как пару дней назад по этому поводу в очередной раз разорялся.

вообще нет способа хоть как-то обезопасить себя

Тайпхинты есть, mypy, абы как, но работает. Ты не совершай ошибки и всё, рецепт прост.

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

Тебе просто конкретные поля получить нужно? Лоадеры по-идеее нужны, чтобы именно объект собрать. Мне ни разу не пригождались. Может я и сам неправильно гино готовлю.

Если мне нужны поля, я просто делаю так же, как сделал бы в дефолтной алхимии:

gino.select([
  Book.x,
  Book.y,
  Author.z
])
WitcherGeralt ★★
()
Ответ на: комментарий от dimuska139

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

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

Не, мне именно объекты нужны - так просто удобней работать. Поэтому, собственно, лоадеры и юзаю. Если б просто поля, я бы реально взял asyncpg и не заморачивался вообще - тогда алхимия нафиг не нужна, потому что ничего не дает особо. На мой взгляд, киллер-фича всяких алхимий-доктрин именно в маппинге на объекты. Не знаю уже, может реально юзать asyncpg, вручную написать гидраторы и юзать какой-нибудь pydantic… С другой стороны, при таком количестве геморроя проще на go многопоток написать, потому что количество трудозатрат ровно такое же, а получится явно надежнее.

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

Я питон юзаю года 3-4, но не в рамках основной специализации. У меня, к счастью, это дело приходится юзать в этот раз только для более-менее шустрой актуализации данных в базе (граббер), так что не сильно критично (а само API у меня не на питоне). А вот прежде чем писать какую-нибудь APIху я бы десять раз подумал, надо ли оно. Тем более тут столько магии, что даже сложно сказать сразу, какой запрос пойдет в базу, и не ясно, что там вообще будет происходить под нагрузкой.

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

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

eternal_sorrow ★★★★★
()

Тред не читал. Fastapi сколько раз рекомендовали?

ei-grad ★★★★★
()
Ответ на: комментарий от eternal_sorrow

А в чем смысл? Использование IDE - это не понты, а элементарное удобство. Это позволяет допускать меньше ошибок и повышает скорость разработки. Про встроенные механизмы для рефакторинга, думаю, писать нет смысла.

Читай документацию и смотри, что возвращает тот или иной вызов

Мне документация никак не подскажет, какие свойства у моей модели.

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

элементарное удобство

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

Мне документация никак не подскажет, какие свойства у моей модели.

ты не знаешь, какие свойства у твоих моделей? ну открой файл, где объявлены модели и глянь, какие у тебя там свойства

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

но не следует воспринимать это как должное

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

где объявлены модели и глянь, какие у тебя там свойства

Ну так понятно, как свойства посмотреть самостоятельно. Но когда IDE после ввода точки тебе предлагает доступные варианты свойств, это ж явно удобней. Моделей может быть спокойно 200-300 штук, как таблиц в базе данных. А если при неправильном вводе IDE выделает цветом, то это тоже удобно. Если этого нет, и надо всякий раз лазать по файлам, чтобы просто глянуть название свойства, то о каком удобстве разработки может вообще идти речь?

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

о каком удобстве разработки может вообще идти речь?

обычном мужском спартанском удобстве

eternal_sorrow ★★★★★
()
Ответ на: комментарий от ei-grad

Ооооо, спасибо!
Я не программист, поэтому в шаблонах проектирования плаваю.

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

Сегодня узнал, что можно указывать комментарий type: int (например) - и тогда IDE «понимает», что в переменной. Но не уверен, что это для более сложных типов прокатит (не проверял)

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

Golang плохо работает с JSON. Поэтому +/- то же самое с Node выходит (последняя просто мега быстра с json). Python хорош в стоимости поддержки, дешевле всего. По скорости если брать sanic/vibora то будет вполне приемлемо

silver-bullet-bfg ★★
()
Ответ на: комментарий от silver-bullet-bfg

Я заметил) Гошка не может отвалидировать json, когда в структуре поле int, а юзер шлет число в кавычках. Потому что пока не замаппишь на структуру, не отвалидируешь. А не замаппишь, потому что при маппинге string на int получишь ошибку без возможности определить в каком именно поле косяк. То есть в go юзер-френдли валидацию нормально не сделать. Либо у меня руки кривые.

По скорости если брать sanic/vibora то будет вполне приемлемо

Так питон же от этого более быстрым не станет. То есть если пилишь API, в котором не заюзать преимущества async (например, логика не позволяет сделать параллельные запросы в БД и т.п.), то по сути преимуществ перед каким-нибудь Flask в скорости не будет никаких.

Кроме того, не увидел для Питона ни одной вменяемой ORM для async. По крайней мере, нормального аналога Typeorm я не нашел. По сути есть только TortoiseORM и Gino, а они мне как-то не зашли.

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

Простите, а где почитать про асинхронное использование SQL баз??? Именно про алгоритмы, логику. У меня это как-то не воображается - сам по себе SQL ну очень синхронный.

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

У тебя бывают случаи, когда для для формирования ответа API требуется сходить в базу/базы несколько раз, а потом результаты объединить в общий json-объект? Если да, то можно ж, если я ничего не путаю, сделать вот так (пулл коннектов только нужен) - и запросы будут выполнены одновременно:


const [rating, recommendations, views] = await Promise.all([
      this.getRating(post.slug),
      this.getRecommendations(post),
      this.countViews(post.slug)
    ]);

Если я ошибаюсь, то поправь.

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

Golang плохо работает с JSON.

Можно пояснить? Насчет скорости не знаю, не проверял. По удобству - в общих случаях шикарно, иногда правда нужно написать немного больше кода, по сравнению с другими языками.

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

Я заметил) Гошка не может отвалидировать json, когда в структуре поле int, а юзер шлет число в кавычках. Потому что пока не замаппишь на структуру, не отвалидируешь. А не замаппишь, потому что при маппинге string на int получишь ошибку без возможности определить в каком именно поле косяк. То есть в go юзер-френдли валидацию нормально не сделать. Либо у меня руки кривые.

Частично правы. Есть обходной путь https://habr.com/ru/post/502176/ . Валидацию подобного плана приходится делать на стороне которая вызывает апи(

Так питон же от этого более быстрым не станет. То есть если пилишь API, в котором не заюзать преимущества async (например, логика не позволяет сделать параллельные запросы в БД и т.п.), то по сути преимуществ перед каким-нибудь Flask в скорости не будет никаких.

Кроме того, не увидел для Питона ни одной вменяемой ORM для async. По крайней мере, нормального аналога Typeorm я не нашел. По сути есть только TortoiseORM и Gino, а они мне как-то не зашли.

Как бы это не было печально - для того же postgresql есть 2 библиотеки которые обеспечивают работу с async. Обе для общих случаев годятся, но во вногих хоть немного нестандартных - все плохо / неудобно.

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

На текущий момент, чтобы IDE всегда «понимала», что в переменной нужно очень тайпхинтов писать самому, так как многих библиотеки их не поддерживают / поддерживают на очень базовом уровне / IDE (PyCharm как минимум) часть написанных тайпхинтов может обрабатывать некорректно.

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

Ну так вот чего-то в последнее время все больше в Питоне разочаровываюсь. Возможно, как-то не так его использую, но постоянно не покидает чувство какой-то ненадежности. Сплошная магия, куда ни плюнь. А IDE откровенные ошибки (как выше пример привел) даже не подчеркивает. Gino так вообще ад какой-то. Ну, это лично мое мнение.

Тоже аналогичные мысли возникают.

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

Если в php есть phpdoc, в js можно использовать тайпскрипт, то в питоне, получается, вообще нет способа хоть как-то обезопасить себя.

Как уже писалось выше - если в питоне все «обмазать» тайпхинтами то код в плане надежности по типам будет сравним с js и тайпскриптом.

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

Я понял, я обычно это решаю сложным запросом с временными таблицами. А иначе, зачем мне SQL?
Алхимией не пользуюсь, пользуюсь peewee. Вроде удобно, как раз в концепции объектов.

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

Согласен. Самое простое решение на текущий момент с имеющимися инструментами.

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

Ты веб пишешь. Он по определению из говна и магии. Чего удивляешься то?

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

если в питоне все «обмазать» тайпхинтами то код в плане надежности по типам будет сравним с js и тайпскриптом

По многословности как жаба, по надежности как жабаскрипт. Клёво!

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

Да, конечно. JSON не реализован на уровне языка (что не удивительно) или стандартной библиотеки (а вот это для меня было внезапно), поэтому для данного формата используются энкодеры/декордеры различной степени кривости. ЕМНИП, самая производительная была от Mail.ru, но могу ошибаться.

Операция выходит дорогая. Когда я тыкал это вместе с ravel (пару лет назад, правда, но бывшие коллеги говорят, что ничего не поменялось в сущности), то все выигрыши в скорости Golang+Ravel сливал и работал на уровне Python+Aiohttp как только доходили до того, что надо принять JSON, мутировать данные и куда-нибудь растолкать + вернуть ответ. Node жеж там где было много работы с JSON (у нас часть данных гонялось в MongoDB) показывал результаты где-то в полтора-два раза лучше. Просто потому, что меньше издержек.

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

JS тут всё равно будет удобнее, ибо JSON - это родной формат VM (JSON - JavaScript Object Notation, ага), так что не удивительно. В остальном - я лично не увидел ничего мегаудобного в работе с JSON ни на одном другом ЯП, всё +/- одинаково, с поправкой на синтаксис/семантику.

silver-bullet-bfg ★★
()
Последнее исправление: silver-bullet-bfg (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.