FastAPI - Роутеры и Файловая Структура #6

Поділитися
Вставка
  • Опубліковано 11 вер 2024

КОМЕНТАРІ • 264

  • @artemshumeiko
    @artemshumeiko  Рік тому +8

    💡 Попробуй онлайн-тренажёр для подготовки к техническому собеседованию: clck.ru/3B5gwP 💡
    Забирай роадмап изучения самого востребованного фреймворка на Python - FastAPI здесь: t.me/ArtemShumeikoBot

    • @vadim7634
      @vadim7634 Рік тому

      pytest и mock хочу на реальном проекте и подробно

    • @forgitmyhub
      @forgitmyhub Рік тому

      ПРоверка итогового проекта на безопасность и взлом

    • @user-ge6og6vx7y
      @user-ge6og6vx7y Рік тому

      Хотелось бы увидеть реализацию функций с аутентификацией и авторизацией. Как это выглядит в коде. Должен куда-то передаваться залогиненный юзер?

    • @user-vf7pc4tn9z
      @user-vf7pc4tn9z Рік тому

      меня горит у меня прокт на запускаться с твоими путями я уже 1 в 1 все с гита скопировал и доабвлял __init__.py и удалял и делал пути auth.models ..models .models разные варинаты он ругаеться что не так ???

    • @user-vf7pc4tn9z
      @user-vf7pc4tn9z Рік тому

      я конечно сильно хейтить не хочу но походу курс надо перезаписать начиная с jwt и этого у меня тупо ниче не работает это пздц

  • @user-qh2ln6fz1s
    @user-qh2ln6fz1s Рік тому +53

    "Я уже изменил файловую структуру, потому что долго было бы делать ее вместе с вами" - напомнило классическое видео "Every programming tutorial"

    • @artemshumeiko
      @artemshumeiko  Рік тому +4

      ахахах именно так :)

    • @0lim_
      @0lim_ Рік тому +6

      О даа именно из-за этого мне этот урок дался не легко

    • @user-gm8gh2gp2v
      @user-gm8gh2gp2v 9 місяців тому +10

      Да, это прям оттолкнуло. Не сделал с нами, так ещё и не показал полное содержимое файлов - сами догадывайтесь что куда пихать. Брух

    • @user-mo1lx6yl5q
      @user-mo1lx6yl5q 6 місяців тому

      @@user-gm8gh2gp2v я нашел гитхаб в описании к видео

    • @ВладиславСиницын-ъ4х
      @ВладиславСиницын-ъ4х 13 годин тому

      @@user-gm8gh2gp2v изменил файловую за 5 минут. ничего сложного. единственное import надо дописывать src) но поиск по файлам выручает.

  • @ionov.lakriz
    @ionov.lakriz Рік тому +52

    Для того чтобы alembic автоматически добавлял дату создания миграции в её название, достаточно раскомментировать следующую строчу в alembic.ini:
    file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s

    • @user-wn4nj6lq9q
      @user-wn4nj6lq9q 6 місяців тому +1

      и почему я не посмотрел ранее бл... нагородил такое --head (Get-Date).ToString('yyyy-MM-dd')

  • @karjicohd1m0nd
    @karjicohd1m0nd Рік тому +36

    для тех кто использует классы , вместо Table и получает при гет запросе ошибку сериализации возвращя ответ через .all()
    попробуйте result.mappings().all()

    • @Wadik_abk
      @Wadik_abk Рік тому

      также получилось устранить ошибку добавлением модели ответов в эндпоинт response_model=List[list] и подключением библиотеки from typing import List соответственно return result без .all(). C mappings лучше понравилось.

    • @cyber_warrior14
      @cyber_warrior14 11 місяців тому +1

      Дай бог тебе здоровья друг, целый час думал в чем загвоздка

    • @user-nf4gt2vw2v
      @user-nf4gt2vw2v 9 місяців тому

      спасибо , оч много времени сэкономил)

    • @helloiveqw5290
      @helloiveqw5290 7 місяців тому +1

      Спасибо) Очень выручил

    • @EvgenUniqueNik
      @EvgenUniqueNik 5 місяців тому

      Вернуть результат помогло. А вот как написан фильтр в where?

  • @TheAmbrosium
    @TheAmbrosium Рік тому +11

    "Мы огорчены, расстроены, но не сломлены" 😀
    Коротко о том, как мотивировать себя когда нужно дебажить код 😀😀

  • @drlem9301
    @drlem9301 Рік тому +9

    такой проникновенный взгляд после фразы - "нам нужно удалить буковку Z" xD
    хотелось бы посмотреть разбор от автора про flush и commit, autocommit и autoflush)

  • @topdich6181
    @topdich6181 Рік тому +6

    Очень классный и полезный урок! Отдельное спасибо за объяснение SQL-инъекций. Да и вообще круто, что ты останавливаешься на таких терминах и подробно разъясняешь их.

  • @mrfang5908
    @mrfang5908 Рік тому +3

    орнул с буковки зет) молодец

  • @Alsurnov
    @Alsurnov Рік тому +12

    Можно писать только классы, а для работы с таблицей при async достаточно сделать user = models.User.__table__. Вот и табличка из класса модели :-) То есть все можно описать декларативным подходом, а императивный просто вызвать через __table__.

  • @saintshell3190
    @saintshell3190 Рік тому +4

    Автор, красавчик!
    Все дружно сидим и учимся)
    ПС. пересмотрел видео, автор 21: 15 сказать что "модель", скорее всего он хотел сказать отображение.
    Как пишут на вики:
    ORM по англ. - это Object-Relational Mapping.
    А по рус. - это объектно-реляционное отображение, или преобразование.

  • @ynerush
    @ynerush Рік тому +14

    Было бы неплохо прикрепить где-то запрос на вставку дефолтных данных в таблицу operation

    • @ballads666
      @ballads666 10 місяців тому

      insert into operations values
      (1, 124, 'H23D8K45M1', 'bond', '2023-10-25 15:30:45', 'выплата купонов'),
      (2, 376, 'C8H6A4N0C7', 'currency', '2023-10-25 14:27:12', 'покупка валюты'),
      (3, 899, 'B0O2N1D1', 'bond', '2023-10-25 13:12:54', 'покупка купонов'),
      (4, 543, 'C1U8R3R3E2N9C2Y', 'currency', '2023-10-25 12:45:01', 'покупка валюты'),
      (5, 198, 'K3D8S0L6F2J5S2', 'currency', '2023-10-25 11:31:23', 'продажа валюты'),
      (6, 617, 'R1B4M1B5I7X', 'bond', '2023-10-25 10:14:27', 'продажа валюты'),
      (7, 445, 'A4O5W7E2Y7F2H3D', 'currency', '2023-10-25 09:09:11', 'покупка купонов'),
      (8, 753, 'E8K5V7I2K9A8L5', 'bond', '2023-10-25 08:02:16', 'покупка купонов'),
      (9, 623, 'T9B0O5O7N3D', 'bond', '2023-10-25 07:01:00', 'продажа валюты'),
      (10, 124, 'P0U3R1C1H5A3S1E', 'bond', '2023-10-25 06:20:51', 'покупка купонов'),
      (11, 376, 'G7H3J9S0V5F9L4', 'currency', '2023-10-25 05:01:47', 'продажа валюты'),
      (12, 899, 'B4Y8Y4H4H7A1N2A', 'bond', '2023-10-25 04:14:22', 'покупка купонов'),
      (13, 543, 'V4A1L5U7T2Y', 'currency', '2023-10-25 03:40:36', 'выплата купонов'),
      (14, 198, 'L4A7T1Y2S8D9V9X1', 'currency', '2023-10-25 02:12:04', 'покупка валюты'),
      (15, 617, '7H3J98Y4H41Y', 'bond','2023-10-25 06:20:51','выплата купонов'),
      (16, 445, 'J9S0V3J98R1B4', 'currency', '2023-10-25 05:01:47','покупка валюты'),
      (17, 753, '1U8R3R3E5O74A', 'bond', '2023-10-25 04:14:22', 'покупка купонов'),
      (18, 623, '0L6FL5U7J9', 'bond', '2023-10-25 03:40:36', 'покупка валюты'),
      (19, 408, 'O7N3J98YU8R3', 'bond', '2023-10-25 02:12:04', 'продажа валюты'),
      (20, 795, '6A4NH230L', 'bond', '2023-10-25 06:20:51', 'продажа валюты');

  • @foxik_cs5845
    @foxik_cs5845 Рік тому +1

    задумался зачем 2 таблицы users и думаю,после видео буду искать,и какое же было мое удивление что ты об этом рассказал! Редко пишу комменты, спасибо за твой труд!)

  • @AnatoliyDekorstyle
    @AnatoliyDekorstyle Рік тому +6

    Интересный смысл использования ORM у вас - онли защита от инъекций!)) А мне казалось главный козырь ORM независимость от вида реляционной БД и легкая замена одной на другую БД (т.е. универсальность)!
    ORM (англ. Object-Relational Mapping, рус. объектно-реляционное отображение) - это технология программирования, которая связывает базы данных с концепциями объектно-ориентированных языков программирования, создавая “виртуальную объектную базу данных” 1. Она позволяет взаимодействовать с базами данных, используя высокоуровневые методы языков программирования, а не SQL-запросы

    • @Noir_Egoiste
      @Noir_Egoiste 11 місяців тому +1

      ORM это слой между твои кодом и бд в свою очередь между бд и orm есть слой ядра Алхимии погугли видосы про нее. Ну и про паттерн Repository.

    • @YmNIKYm
      @YmNIKYm 10 місяців тому

      ну все же ORM это преобразование данных из таблиц в объекты со всеми связями, а все остально - это уже фичи.

    • @YGNETATEL_3000
      @YGNETATEL_3000 8 місяців тому

      ORM - Object-Relational model ? . автор senoir или еще middle ? я даже еще не джун

  • @BestDron
    @BestDron Рік тому +8

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

  • @SeRGKIM13
    @SeRGKIM13 Рік тому +3

    Артём, спасибо большое за твои уроки. Отличная подача материала, хорошая картинка, звук. Продолжай в том же духе!

    • @artemshumeiko
      @artemshumeiko  Рік тому +1

      Спасибо! Впереди ещё много интересных уроков ;)

  • @user-kl7gh2yb7p
    @user-kl7gh2yb7p Рік тому +2

    Про ассинхронный Alembic, в официальной документации есть раздел Using Asyncio with Alembic. Да, Alembic напрямую не предоставляет async api, но использовав async template при выполнении команды alembic init есть возможность использовать SQLAlchemy Async engine для запуска миграций.

  • @milord3089
    @milord3089 Рік тому +4

    я уже довольно продолжительное время работаю на FastAPI и даже при разделении на сервисы нет необходимости созданий множества Metadata, лучшей практикой я считаю было бы созданием глобального metadata и к ниму привязать все таблицы. А в alembic просто импортировать ваши таблицы и глобальную metadata.

    • @artemshumeiko
      @artemshumeiko  Рік тому

      Действительно, хороший вариант! Спасибо

  • @Anthony_Private
    @Anthony_Private Рік тому +1

    Очень годно)
    Я в х2, с перемоточками, смотрю и закрываю пробелы)

  • @alekseyveld7559
    @alekseyveld7559 Рік тому +1

    Это лучший канал по FastApi, у меня все)

  • @milord3089
    @milord3089 Рік тому +5

    Хотелось бы увидеть видео про тесты с sqlalchemy orm с подвязкой тестового бд

  • @hopaloba800
    @hopaloba800 Рік тому +1

    Артем, большое спасибо за твой труд!

  • @DastanAshimkhan
    @DastanAshimkhan Рік тому +1

    Здравствуйте, очень хорошо и понятно объясняете. Спасибо Вам.

  • @aaabbbcccddd
    @aaabbbcccddd Рік тому +4

    Всё супер, картинка, звук, подача материала, единственное не нравится когда вы вставляете кусок кода для ускорения процесса (у нас его нету, а брать с репозитория не охота, т.к. хочется всё по шагово вникать, так сказать строчка за строчкой, а тут в начале видео бац и вся структура проекта изменилась..... взрыв мозга))) )

  • @madikhan-only
    @madikhan-only Рік тому +1

    Просто лучший! Спасибо огромное за курс

  • @user-yh5ir4mv9m
    @user-yh5ir4mv9m 8 місяців тому +1

    Спасибо огромное за обучающий материал! очень много интересного для себя узнал! Всем. кто критикует автора, в комментах, почему бы вам не снять свои обучающие видео? в ютубе пока что это лучшие видео по fastapi на руссом языке

  • @user-nl2mc5le7o
    @user-nl2mc5le7o Рік тому

    Спасибо большое за качественный контент! понятно, приятно смотреть и слушать! Артем, ты -лучший!

  • @filippov_es
    @filippov_es Рік тому +8

    Отличный урок, спасибо большое. На моменте отправки ответа с данными из базы у меня падала ошибка о том, что фастапи не может сериализовать данные в JSON ([TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have __dict__ attribute')])
    Некоторое время поисков и попыток получилось решить просто прогоном всех записей циклом через схему модельки с укакзанием полей. Криво, но работает. Надеюсь в следующих уроках решим вопрос)

    • @offline911
      @offline911 Рік тому +2

      Та же проблема, никак не мог понять в чем дело

    • @user-en3qo2zb8i
      @user-en3qo2zb8i Рік тому

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

    • @user-en3qo2zb8i
      @user-en3qo2zb8i Рік тому

      Единственное, я просто создал список словарей, и в цикле в каждый словарь добавлял значения. Вы так же или как-то по-другому? Слово "через схему" насторожило

    • @filippov_es
      @filippov_es Рік тому

      @@user-en3qo2zb8i через pydantic схему. Вообще по-хорошему делать с помощью декларативного метода модельки (классом). Тогда можно все сильно проще организовать

    • @flower-py
      @flower-py Рік тому +1

      @Vladislav Erekeshov ты лучший, спасибо большое.
      Дату в модель тоже добавил строкой "date: datetime.datetime"

  • @antonypetrenko4458
    @antonypetrenko4458 9 місяців тому

    Подписался. Поставил лайк. Из чего-то хорошего... скажу что у ВАС имеется преподавательский талант :)

  • @andrewbondaryuk
    @andrewbondaryuk Рік тому +4

    ORM - Object-Relational Mapping

  • @PrusakovVladimir
    @PrusakovVladimir Рік тому

    Большое спасибо за урок, он был очень познавательным!

  • @muhammadumarsotvoldiev9555
    @muhammadumarsotvoldiev9555 Рік тому

    Спасибо за ваш труд!

  • @defend00r
    @defend00r Рік тому

    :D ахах это лицо после иправления даты, харош!!!11

  • @echernyshov
    @echernyshov Рік тому

    Спасибо. Хорошая работа. Продолжайте делать обучающие видео, у вас отлично получается.

  • @santex85
    @santex85 Рік тому

    про организацию файловой системы отдельное спасибо

  • @valeriivolkov_ua
    @valeriivolkov_ua Рік тому

    Пишу какой-то хороший комментарий: твои обучалки великолепны! Спасибо!

  • @Pav.rakhmanov
    @Pav.rakhmanov Рік тому +1

    Лайк за картинку и звук

  • @user-jy2qi1ds4f
    @user-jy2qi1ds4f Рік тому

    Отлично! Спасибо за уроки!

  • @Павел-ю5и
    @Павел-ю5и 2 місяці тому

    Артем спасибо за такие классные видео. Ты большой молодец.)

  • @orthodox-chanel
    @orthodox-chanel 23 дні тому +1

    почему-то алхимия выдала кортежи а не json/dict как на видео, помогла типизация
    class OperationModel(BaseModel):
    id: int
    quantity: str
    figi: str
    instrument_type: str
    date: datetime.datetime
    type: str
    @router.get('/{operation_type}', response_model=List[OperationModel])
    async def get_specific_operation(operation_type:str , session: AsyncSession = Depends(get_async_session)):
    query = select(operation).where(operation.c.type == operation_type)
    result = await session.execute(query)
    res = result.all()
    return res

  • @Vegas_Silver
    @Vegas_Silver Місяць тому

    Про букву Z было смешно ))) Классный урок, спасибо !

  • @adammason482
    @adammason482 Рік тому

    Спасибо за урок!

  • @maksiamchuk8774
    @maksiamchuk8774 Рік тому +4

    Здесь во избежание проблем нужно удалить буковку Z. *взгляд в камеру*

  • @user-tu7tr3bn8g
    @user-tu7tr3bn8g 5 місяців тому +2

    Добрый день. Подскажите почему на видео не было ошибки при получения get запроса(return result.all())? 29 минута. У меня была ошибка ValueError: [TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have dict attribute')]. Когда исправил на return result.mappings().all() ошибка пропала.

    • @artemshumeiko
      @artemshumeiko  5 місяців тому +3

      старая версия алхимии в видео

  • @Artem-wk1vn
    @Artem-wk1vn Рік тому +5

    Спасибо за урок) А можете в будущем сделать пример с микросервисной архитектурой на FastAPI(с парой сервисов) ?

    • @artemshumeiko
      @artemshumeiko  Рік тому +2

      Пожалуйста! :) Скорее всего будет дополнительный сервис для рассылок по почте

  • @eugeneyakimenko8843
    @eugeneyakimenko8843 Рік тому

    Спасибо за видео, все очень доступно и понятно!

  • @saidhonsaidmavlonov85
    @saidhonsaidmavlonov85 Рік тому +1

    спасибо брат за уроки

  • @Ctac7878
    @Ctac7878 Рік тому

    Артём, вы делаете богоугодное дело! Спасибо большое за проделанную работу.

  • @djambur
    @djambur 10 місяців тому

    Это самый "плохой" комментарий! Спасибо за это видео и плейлист в целом! ))))

  • @bomarshee
    @bomarshee Рік тому +1

    Артем спасибо за видео! И запрос на заполнение INSERT INTO public.operation
    VALUES (3, 1,'TCGA', 'bond', '2022-11-21 12:44:00', 'Выплата купононов'),(2, 10,'TCGM', 'bond', '2012-10-21 12:44:00', 'Покупка ценных бумаг');

    • @fresh_wind87
      @fresh_wind87 Рік тому

      спасибо хоть на этом, автор благополучно забить на это решил

  • @nikolay9898
    @nikolay9898 Рік тому +3

    Что то я не нашел рабочего решения, гет запрос на получение из бд из таблицыс операциями ошибка :raise ValueError(errors) from e
    ValueError: [TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have __dict__ attribute')]

    • @kayriat-youtube39
      @kayriat-youtube39 Рік тому

      Попробуй вместо result.all() использовать result.scalars().all()

    • @dmitry-lz1ny
      @dmitry-lz1ny Рік тому +2

      @@kayriat-youtube39 тогда будет выводится только id у всех результатов.

    • @ZZZMerk
      @ZZZMerk Рік тому

      Тоже встрял на этом, пока решения не нашел(

    • @artem_raudsep
      @artem_raudsep Рік тому

      Кто-нибудь нашел решение данной проблемы?

    • @ZZZMerk
      @ZZZMerk Рік тому +3

      @@artem_raudsep return [dict(r._mapping) for r in result]

  • @nicudomenti5235
    @nicudomenti5235 Рік тому

    хороший контент по FastAPI !

    • @artemshumeiko
      @artemshumeiko  Рік тому

      Спасибо :) Впереди еще много контента

  • @gayratsaidakhmedov5451
    @gayratsaidakhmedov5451 5 місяців тому

    Спасибо
    из своего опыта скажу - db инициализацию (создание таблиц, триггеров, функций, ...) стоит выносить в отдельную папку
    будет меньше забот при масштабировании проекта

  • @voronovmaksim88
    @voronovmaksim88 3 місяці тому

    Спасибо за видео.

  • @andrewbright7487
    @andrewbright7487 4 місяці тому

    Ну плохой комментарий, так плохой комментарий😂, а так классная серия видосов, спасибо большое)

  • @Dmitriy_Olegovich_95
    @Dmitriy_Olegovich_95 8 місяців тому +1

    Зачем нужны pydentic models - если коротко?

  • @nailabdullin7096
    @nailabdullin7096 Рік тому

    огромное спасибо =)

  • @7IdE
    @7IdE Рік тому

    "...и напиши какой-нибудь хороший комментарий. Или плохой. Неважно."
    На самом деле, вот эта фраза во мне стриггерила крайне негативное отношение.
    Да, я понимаю, что, технически, без разницы, будут тебя в комментах восхвалять или мешать с гавном - это все равно будет +1 в COUNT(comments), а именно это является базой для алгоритмов Ютуба - но, все же, прям настолько людей считать мясом/биомассов/циферками - ну такое себе.
    Я, в целом, мог бы попытаться додумать, что ты, возможно, имел ввиду что-то типа "...напишите любой коммент, который будет выражать ваше мнение, каким бы оно ни было" - но есть вероятность, что реальность будет именно такова, как мне показалось изначально.
    Но это так, придирка.
    А плейлист зачетный - реально классно все рассказываешь.

  • @TheMurodilla
    @TheMurodilla Рік тому

    годный контент 👍

  • @shalaginovdanila5421
    @shalaginovdanila5421 Місяць тому

    28:47 Артëм, ты откуда взял данные для этой таблицы? Дай ссылку.

  • @rustammamedov1508
    @rustammamedov1508 Рік тому +1

    36:56, хорошая отсылка, ахахахаха

  • @supreltd
    @supreltd 7 місяців тому

    Для хранения float используется Decimal.

  • @__-fx5gd
    @__-fx5gd 6 місяців тому

    Большое вам спасибо! Начал изучать FastAPI с 0 по вашим урокам, очень подпольные и понятные видео. Но никак не могу разобраться в структуре put запроса для обновления данных в таблицах. Не могли бы немного подсказать как бы выглядел такой запрос для обновления данных на вашем примере(для обновления данных в таблице с операциями). Буду очень благодарен.

  • @user-ge6og6vx7y
    @user-ge6og6vx7y Рік тому +1

    Спасибо за курс, очень полезно.
    1. Расскажите про библиотеку SQLModel от создателя FastAPI (показалась очень удобной).
    2. Не могу понять как, при использовании декларативного метода описания таблиц, делать миграции через алембик? Где брать метадату?

    • @artemshumeiko
      @artemshumeiko  Рік тому +4

      1. Изучу, спасибо за предложение
      2. При декларативном стиле объявляется переменная Base = declarative_base(), от которой наследуется наши модели. В файл env.py импортируется переменная Base (аккумулирующая в себе данные о созданных моделях) и в target_metadata передаётся Base.metadata
      Больше информации тут: docs.sqlalchemy.org/en/13/orm/extensions/declarative/basic_use.html

  • @Denzi33
    @Denzi33 2 місяці тому

    Легенда...

  • @kaluginpeter
    @kaluginpeter 26 днів тому

    36:55 хах, неоднозначно получилось)

  • @Qustoos
    @Qustoos 9 місяців тому +1

    Где можно найти скрипт добавления данных в бд? В репе нет файла.

    • @Leha_from_Zavod
      @Leha_from_Zavod 7 місяців тому

      не решил проблему брутфорсом?))Буду благодарен если сможешь поделиться

  • @user-dy5sv1gx4v
    @user-dy5sv1gx4v Рік тому

    Спасибо бро !

  • @vladratnikov5705
    @vladratnikov5705 Місяць тому

    36:55🤣 в этот момент они могут только появиться

  • @mustafinmp
    @mustafinmp 2 місяці тому

    Сейчас в sqlalchemy что-то изменили, и теперь нельзя получить список словарей (объектов), написав result.all() (возвращается объект типа Sequence[Row[_TP]]). По этой теме даже появился вопрос на Стаковерфлоу, посвященный именно этому моменту именно из этого видео. Вместо result.all() теперь работает что-то вроде [dict(r._mapping) for r in result]. Надеюсь, с более сложной структурой это также будет работать.
    P.s. увидел в комментариях более элегантное решение через result.mappings().all()

  • @awesomeex5821
    @awesomeex5821 3 місяці тому

    урок про файловую структуру - "я изменил файловую структуру без вас потому что с вами было бы долго"

  • @unix3d
    @unix3d Рік тому

    За контент спасибо, что занимаетесь просветительской деятельностью!
    А вот теперь ложка дёгтя:
    Может быть из-за опыта в корпоративной разработки (более 15 лет) и на другом языке (С++/C#), но назвать папку со всем что относится к сервису сваленную в одну кучу best practices это конечно очень по питонячи. И да понятно почему такой подход, что бы не заворачиваться с импортами, но эта "архитектура" файловой структуры ИМХО не есть лучшие практика даже с 2К звёзд. И Вот один из кейсов которые могут возникнуть возьмём exceptions понятное дело что у auth, aws, etc... они зачастую свои, но есть и общие которые лежат в корне src подход в принципе на 3- потому что exceptions это многогранное название файла говорящие о его содержании ровно ничего кроме того что "Уважаемый читатель кода, будьте так добры откройте меня и я вам покажу все прекрасные исключения которые в меня поместил мой создатель, что бы создатель смог отлавливать нештатные ситуации в своём коде". Да я понимаю что это так по питонячи набросать всё в один файл, а дальше тащить всё из него не заворачиваясь над импортами, но и читать этот код становится труднее так как приходятся открывать файлы для того что бы посмотреть что за код в этом файле, а не брать в расчёт нейминг файла. Как делаю это я и даже на Python выношу все exception в отдельные группы с разбивкой по файлам, где в именах файлов какие действия обрабатывают exceptions, да приходятся ручками слегка шаманить в __init__.py прописывая импорты, но при взгляде на структуру, как опять мне кажется я чётко представляю из названия файла, какие внутри него возможности, будь exception, model, etc... Может я из старой школы но даже в нейминге фабрик я дописываю factory и делаю это на автомате.
    Ну если рассмотреть данную практику не с точки зрения PET проекта, а с точки зрения DDD то новому члену команды приходится шерстить однотипные файлы что бы построить в голове что где лежит, для бизнеса это трата средств на сотрудника который делает ровно ничего, а просто изучает структуру проекта, что бы не дай бог не написать новый exception в очередном файле exceptions.py который будет на 99% похож на тот что был в файле exceptions.py, но на уровне выше. Всё то же самое и с моделями, а если ещё принять, что модели бизнес логике это совсем немного не сущности DB слоя и для трансфера между слоями нужны DTO, то эта "лучшая практика" превращается в свалку всего и вся. Но как говорится это питонячий путь.

    • @artemshumeiko
      @artemshumeiko  Рік тому +1

      Спасибо за ваш развернутый комментарий!
      Я частично согласен с тезисами, если речь идет о проекте среднего или большого размера (какими зачастую являются коммерческие проекты), хоть и встречаю примеры использования подобной в видео структуры в крупных open-source проектах.

    • @BestDron
      @BestDron Рік тому

      Есть куча проэктов на Django где люди вообще не слышали что такое сервисы и толкают их в views или models.
      Эти проэкты годыми работают на продакшине .
      Python язык для новичков, которые не хотят строить абстракции над абстракциями , не хотят ломать голову о чистой архитектуре.
      Я понимаю что програмисты C# строят патtерн Репозиторий над EntityFremework, хотя он там внутри дай только усложнить.
      На деле бизнес ценит скорость разработки . Если в пайтоне будут расказывать сразу про правильную архитектуру , он совсем не покажиться легким. Не стоит усложнять простое с опытом все придёт.

    • @unix3d
      @unix3d Рік тому

      @@BestDron , Бизнес ценит скорость только на этапе старта, что бы иметь выгодные конкурентные позиции, далее бизнесу важна стабильность (у нас в проекте планы фичей до Q4 2023 расписаны) так как нестабильность приносит финансовые затраты бизнесу и это ему не нравится. Да не буду спорить что на старте как язык прототипирования и пробы идеи с питонякой поспорить ну оооочень сложно, но на дистанции при условии того что идея выстрелила питоняка уступает место другим языкам и это логично в следствии своих скоростных характеристик. В тырпрайзных решениях Вы довольно редко увидите python как core яп, в основном там C#/Java/Rust (с недавнего времени) и это не связанно с тоннами легаси которые присущи любому крупному проекту (из жизни в проекте над котором я работаю (финтех) есть библиотека с датой компиляции 1998 год написана на С и она в боевом проекте уже 25 лет, и да в планах на Q3 актуализировать её на C#). Но говорить что python не используется в крупных проектах это обманывать самого себя, он используется но его место это больше решение сопутствующих проблем когда нужно вот прям тут и быстро. Сколько раз было когда требовалось решение прикладной задачи и я выбирал Python против С#/Rust и мне было не особо интересно что код будет медленнее делать работу, главное что я потрачу меньше времени для самого решения этой задачи. Я намерено не затрагиваю js и его ипостаси для бэка потому что имею личную неприязнь к этому яп. Хотя в одном не большом холиварчики нода уделала по скорости гошечку.
      По поводу чистоты архитектуры, ну честно это не про разработчиков на python (привет Protocol и Generic). Если с самого начала не объяснять разработчикам основы чистой архитектуры то даже с опытом это не придёт, потому что сила привычки возьмет в верх. Выше пример с 2К звездочками и свалкой явный показатель. Вы часто видели проекты на python следующие принципам SOLID ? Вот попробуйте сейчас коллегам/друзьям/знакомым которые пишут на python начать рассказывать про IoC/DI да на Вас будут смотреть с квадратными глазами, а потому что они привыкли нужна зависимость импорт->инстанцирование погнали использовать и такое размазано по всем файлам это уже привычка у них. или полезут искать в pip библиотеку DI контейнерезации, а то что есть Pure DI и для его реализации не нужны сторонние библиотеки они не задумываются потому что это опять дело привычки. Аналогично дело обстоит с подходом программированием от интерфейсов, да потому что лень это же надо продумать, а тут х..як и уже в проде.
      Да на python можно писать сложные продуманные архитектурные решения, но в виду его низкого порога вхождения (привет бота писателям на aiogram) этим обычно пренебрегают в угоду быстроты разработки и быстрой выкотки готового решения в прод. Но в крупных решениях для бизнеса Вы как разработчик всего лишь винтик в большом механизме и механизм не должен тормозить и ни дай бог остановится если Вас извлечь из механизма. И вот тут уже совершено другие методологии разработки, так как чем меньше новый винтик потратит времени на изучение проекта тем лучше для бизнеса и тем меньше нагрузка на других членов команды пока этот винтик притрётся и заменит предыдущего своего коллегу.
      Ну зачем же так про нам (разработчики на С#) лишь бы усложнять, Entity Framework это концептуально та же ORM что SQLAlchemy, да в python отличается подход работы с коллекциями и с ORM в .NET этот подход один LINQ и да python разработчику столкнувшимся с ORM в первый раз довольно непонятно как так через "." писать что то похоже на SQL но не SQL. В .Net с этим меньше проблем потому что с коллекциями Вы используете LINQ, что с ORM вы опять используете LINQ. И где же тут усложнение ?

    • @unix3d
      @unix3d Рік тому

      @@artemshumeiko , M в ORM это Mapping, Мне понравилось что объяснением Вы рассказали что это представление данных, а в комментариях по коду M это не какая то абстрактная сущность на которую применяется действие и бла бла бла, а сразу к делу М на выходе модель и точка.

    • @BestDron
      @BestDron Рік тому

      @@unix3d ORM Entity Framework и sqlalchemy небо и земля. Я писал о том, что EntityFramework из коробки реализует репозиторий и Unit of Work об этом пишут его разработчики. Но c# программисты делают его всё равно.
      EntityFramework может вызывать функции sql из кода на c# сравнивать две эти ORM не благодарно. C# отличный язык с огромной кучей синтаксического сахара, там одну задачу можно решить 50 разными способами, что пугает новичков. У меня есть коллега разработчик на c#, он говорит когда они ввели метода интерфейсов реализующие по умолчанию их мир на c# пошатнулся. Для них в голове интерфейс был абстракцией . Теперь каждый junior пытается пропехнуть эту в проду.
      Так нормальный мы холивар развели в комментариях по языку c# под видео на питоне.))

  • @РамазанАязбек
    @РамазанАязбек 10 місяців тому +1

    когда из базой данных получили данные и вернули в интерфейсе через
    return result.all()
    вот такая ошибка
    raise ValueError(errors) from e
    ValueError: [TypeError('cannot convert dictionary update sequence element #0 to a sequence'), TypeError('vars() argument must have __dict__ attribute')]
    то есть не принимает dict

    • @user-tv9fv2el8u
      @user-tv9fv2el8u 10 місяців тому +2

      result.mappings().all() решает вопрос:) (у самого была такая проблема и ответ нашел здесь в кометах)

    • @dmitrybokhan1837
      @dmitrybokhan1837 7 місяців тому

      @@user-tv9fv2el8u у меня тоже самое, mappings() помог, а что это? почему так происходит?

    • @shalaginovdanila5421
      @shalaginovdanila5421 Місяць тому

      ​@@user-tv9fv2el8uТолько он выводит пустой список.

  • @vladimirmaznev9396
    @vladimirmaznev9396 Рік тому +1

    после реструктуризации проекта у Артёма на гитхабе и в видео импорт происходит так:
    from operations.models import operation
    у меня только с указанием каталога src:
    from src.operations.models import operation
    если убрать префикс src, то возникает ошибка:
    ModuleNotFoundError: No module named 'operations'
    вставка файла __itit__.py ничего не изменила.
    может быть, это не слишком принципиально, но хотелось бы понимать, почему у Артёма код работает

    • @unlessiamwrong
      @unlessiamwrong Рік тому

      Привет, такая же проблема. Удалось выяснить почему?

    • @44animexxx79
      @44animexxx79 Рік тому

      @@unlessiamwrong Я тоже столкнулся с данной проблемой, одно из решения, просто скачайте с гитхаба папку с проектом 6 урока, и продолжайте обучение

    • @vladimirmaznev9396
      @vladimirmaznev9396 Рік тому

      @@44animexxx79 скачал (кстати, можно клонировать только весь проект, одна папка не скачивается), открываю любой файл, относительные пути не работают. нужно делать абсолютные.
      возможно, потому что я работаю под Win10? у автора вроде бы Linux

    • @cracktaylor4904
      @cracktaylor4904 Рік тому

      Такая же беда. Я в файл __init__.py добавил следующий код:
      import os
      import sys
      sys.path.append(os.path.join(sys.path[0], 'src'))
      А приложение запускаю теперь через: uvicorn src.main:app --reload
      Но почему у Артема работает и без этого, а у меня нет, я так и не понял)

  • @user-qh2em5cb2i
    @user-qh2em5cb2i Рік тому

    Спасибо

  • @dmitryrotanin
    @dmitryrotanin Рік тому

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

  • @DICEt
    @DICEt 11 місяців тому

    Хороший комментарий для продвижения канала

  • @Bupyc2006
    @Bupyc2006 Рік тому

    спасибо за уроки, у меня вопрос : я не могу найти в коде место, где мы пускаем только авторизованных пользователей на путь "/operations" - помогите найти и разобраться

  • @somethinggood5951
    @somethinggood5951 6 місяців тому

    Thank you!

  • @user-ec7wk1cr6x
    @user-ec7wk1cr6x Рік тому

    24:08 - блин, прикольно

  • @user-ts6wk3mu2l
    @user-ts6wk3mu2l Рік тому +2

    Артём, извините что по имени, ещё таких два вопроса.
    1. Будет ли рассказано про gunicorn поверх uvicorn (читал, что так делают, но так и не понял зачем)
    2. Может было бы проще создавать подключение к БД через роутер on_event("startup") и закрытие через on_event("shutdown"). У кого-то видел в коде так было реализовано подключение... Заранее спасибо за ответы!

    • @artemshumeiko
      @artemshumeiko  Рік тому +3

      Спасибо за вопросы!
      1. Для проекта с небольшим количеством пользователей и низким rps можно оставить только uvicorn. Если проект среднего размера и находится на одном сервере, Gunicorn + Uvicorn могут работать в связке, задействуя больше CPU, но обеспечивая больший rps. Если используется кубернетес, можно оставить uvicorn на каждом сервере.
      Больше информации тут: fastapi.tiangolo.com/deployment/docker/#single-container и тут: stackoverflow.com/a/71546833/18406890
      2. Скорее всего тут вы правы. Упомяну об этом в следующих видео

  • @paveltarnopovich2574
    @paveltarnopovich2574 Рік тому

    Отличный материал! А как связать модели из двух разных сервисов. Вот например, что если бы я хотел связать таблицу operation с таблицой User.

  • @user-rw4nl8qf2g
    @user-rw4nl8qf2g Рік тому

    интересно почему сразу дату в миграции alembic не добавляет, в том же Laravel для каждой миграции дата и время ставится по умолчанию...
    Хотя там вероятно миграции немного по другому устроены, но всё же...
    В django миграции тоже нумеруются, если не ошибаюсь.

  • @user-lt1jo7gt8i
    @user-lt1jo7gt8i Рік тому

    Артем, добрый день!) Подскажите, планируете ли курс делать с практическими заданиями , например на степике? Потому что таковых действительно нет)

    • @artemshumeiko
      @artemshumeiko  Рік тому

      Спасибо за идею! На степике в ближайшее время не планируется. Чтобы создать качественный курс, нужно довольно много времени и сил, чем я пока не располагаю.

  • @mmmm45454
    @mmmm45454 16 днів тому

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

  • @user-tu7tr3bn8g
    @user-tu7tr3bn8g 5 місяців тому

    Интересно на платном курсе тоже такие подставы есть, где лектор что-то делает сам, а ты потом должен догадаться что да как?

  • @supreltd
    @supreltd 7 місяців тому

    Чтоб избежать sql - инъекций в сырых запросах_забудьте про f-string.
    Для этого есть свой синтаксис. Например asyncgp передает данные через $1, $2 и тд
    query = """SELECT some FROM some_table WHERE some = $1"""

  • @user-wn4nj6lq9q
    @user-wn4nj6lq9q 7 місяців тому

    изначально стал выстраивать структуру, и пишу с применением ооп

  • @twelfth4927
    @twelfth4927 5 місяців тому

    Ребят, я не уверен, но не лучше будет использовать структуру
    Operation = OperationOrm(**new_operation.dict())
    session.add_all(Operation )
    await session.commit()
    Урок год назад вышел, я пока не врубаю из-за отсутствия опыта что лучше делать таким образом или использовать операции select, insert и тд из алхимии.

  • @user-in1om1lx3f
    @user-in1om1lx3f Рік тому +1

    У меня выдает 500 ошибку, если return result.all().Работает только - return result.scalars().all().Почему?

    • @ynerush
      @ynerush Рік тому

      Получилось решить? у меня так же

    • @user-in1om1lx3f
      @user-in1om1lx3f Рік тому

      @@ynerush Ответ в комментариях под этим видео - ua-cam.com/video/qvzQWBEBHYw/v-deo.html Если коротко, то автор использует надстройку над синтаксисом.Без нее scalars обязателен.

    • @IgorVin1988
      @IgorVin1988 Рік тому

      @@user-in1om1lx3f а что за настройка? Это из того треда на SOF? Я чет не понял, что именно приводит к такому результату?

    • @paul12721
      @paul12721 Рік тому +2

      return [dict(r._mapping) for r in result]

  • @deadproxcee
    @deadproxcee Рік тому +1

    Может глупый вопрос, может уже многое поменялось. Но при выполнении query = select(operation).where(operation.c.type == operation_type)
    result = await session.execute(query), result.all() возвращает массив кортежей, что влечёт ошибку с при передаче в return. Может кто нибудь пояснить по этому поводу? Что изменилось или я что то не так делаю?

    • @artemshumeiko
      @artemshumeiko  Рік тому

      Попробуйте result.scalars().all()

    • @viachaslaukulchynski8856
      @viachaslaukulchynski8856 Рік тому +4

      return [dict(r._mapping) for r in result]

    • @ozzyoz6824
      @ozzyoz6824 Рік тому

      Вопрос отличный, кучу времени убил на поиски решения...Вячеслав, спасибо за подсказдку!

  • @user-yt9ei5ok7n
    @user-yt9ei5ok7n 6 місяців тому

    хороший комментарий

  • @AlexanderDev
    @AlexanderDev 9 місяців тому

    Привет! Скажи, пожалуйста, а ты пробовал вместо Алхимии использовать Pony ORM? Мне кажется, с их веб-интерфейсом проектировки БД - очень удобный инструмент

    • @artemshumeiko
      @artemshumeiko  9 місяців тому +1

      Не пробовал. Пойду почитаю про него

  • @haskelllisp5998
    @haskelllisp5998 Рік тому +4

    что бы не удалять Z Column("date", type_=TIMESTAMP(timezone=True))

  • @DarthZiel
    @DarthZiel Рік тому

    Хороший комментарий

  • @fugitiveom
    @fugitiveom 10 місяців тому

    Зачем такие танцы с metadata? Почему это лучше, чем просто target_metadata = Base.metadata?

  • @vanadoo5836
    @vanadoo5836 11 місяців тому

    36:55 ахахах :D

  • @user-mr5vc5id2s
    @user-mr5vc5id2s 3 місяці тому

    Добрый день, кто знает, как сделать валидацию существования внешнего ключа в БД через Pydantic? Чтоб если передаем Id внешнего ключа, которого нет в бд, не возвращала 500 ошибку.

  • @fykvon296
    @fykvon296 Рік тому

    лайк за момент 36:57-37:00😂

  • @artemkartashov3741
    @artemkartashov3741 9 місяців тому

    Привет, объясните, пожалуйста, зачем автор создаёт в src/auth/models.py сначала таблицу user, а потом ниже класс User, с точно такими же полями. Как я понимаю, класс юзер идёт в ОРМ алхимии, но зачем тогда нужна таблица? Она, если я не ошибаюсь, никуда не импортируется и не используется вовсе.

    • @artemshumeiko
      @artemshumeiko  9 місяців тому

      Да, она лишняя, можно обойтись классом

  • @PhilippTemkin
    @PhilippTemkin Рік тому +1

    Автор, Я не претендую ни на какие титулы в программирование, и не являюсь программистом вовсе, смотрю подобные видео для саморазвития, и так, написать какую-нибудь штуку и посмотреть - заработает или нет.
    Я в упор не понимаю для чего эти миграции. Почему нельзя в базе данных (MySQL, SQLite, Postgress - админке) напрямую не задать нужные таблицы и связи ? ведь работы прописывая их в "миграциях" и в интерфейсе программы администрирования БД столько же. Вот никогда не понимал этого прикола

    • @artemshumeiko
      @artemshumeiko  Рік тому +1

      Когда разрабатываешь бэкенд и бд в одиночку, пожалуй, миграции будут лишним грузом. Но когда бэкендеров больше, чем 2 (пускай один разрабатывает бэкенд и бд, а остальной(ые) только бэкенд), то резко увеличивается количество времени, затрачиваемое на обмен информацией об обновлении таблиц в базе данных. Таким образом, конструируя базу данных прямо на бэкенде, разработчики могут в любой момент увидеть текущее состояние бд, а также все предыдущие, не залезая в саму базу и не мучая администратора бд своими вопросами :)
      Помимо этого, часто коммерческие продукты имеют версии (1.0, 2.0 и и т.д.), которые удобно поддерживать через миграции

    • @PhilippTemkin
      @PhilippTemkin Рік тому +1

      @@artemshumeiko теперь стало понятно. Спасибо!