Найти тему
Computer Pro

ORM SQLAlchemy часть 2

Продолжаем изучать Алхимию SQL, первая часть:

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

На примере таблиц из предыдущего ДЗ:
1. Проведите доработку моделей:
добавьте к моделям связи и внешние ключи;
опишите каскадное поведение;
опишите способы подгрузки данных — используйте различные типы «жадной подгрузки»;
реализуйте связь MANY-TO-MANY для таблиц students — receiving_books — books с помощью AssociationProxy.
2. Добавьте роуты во flask-приложение:
получите количество оставшихся в библиотеке книг по автору (GET — входной параметр — ID автора);
получите список книг, которые студент не читал, при этом другие книги этого автора студент уже брал (GET — входной параметр — ID студента).Пример:
Я брал книгу Льва Толстого «Война и мир», роут должен вернуть другие произведения этого автора, которые есть в библиотеке.
получите среднее количество книг, которые студенты брали в этом месяце (GET);
получите самую популярную книгу среди студентов, у которых средний балл больше 4.0 (GET);
получите ТОП-10 самых читающих студентов в этом году (GET).
3. Создайте роут, который будет принимать csv-файл с данными по студентам (разделитель «;»). Используя csv.DictReader, обработайте файл и задействуйте Session.bulk_insert_mappings() для массовой вставки студентов.
4. По желанию. Создайте триггер события перед вставкой в таблицу students. Триггер должен проверять, что номер телефона имеет формат +7(9**)-***-**-**, где * — цифра от 0 до 9.
Что должны получить на выходе?!
Умение связывать таблицы с помощью ORM.
Понимание каскадного поведения.
Понимание подгрузки данных.
Работа со сложными запросами (group_by, order_by, subquery, func).
Работа с массовой вставкой.
Создание ORM Events.

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

Данное задание я уже делал с использованием Postgresql. После выполнения хотел было перевести на Sqlite, но там появились проблемы совместимости. Почему-то не заработало autoincrement=True, в поле id. Выскочила какая-то ошибка и я уже не стал заморачиваться с поиском решения. А просто спросил у куратора о возможности принять задание на базе postgres.

Был создан новый проект, причем даже не на гитлаб или гитхаб, а на гитвёрс от Сбера. Я подумал - а почему бы не попробовать отечественный сервис гит?! А то санкции и прочая дичь... Докерхаб тому в пример.

Были использованы следующие зависимости:

возможно тут присутствуют и лишние модули...
возможно тут присутствуют и лишние модули...

Данное задание я выполнил как полноценный сайт, со страничками, но без особого дизана, из дизайна только подключенная библиотека CSS в HTML коде. Сайт выглядит так:

-3

Дизайн проявляется в таблицах, примерно так:

-4

Самое сложное в данной работе - понять как работает AssociationProxy. И не факт что я осознал как оно работает, потому как сто раз прочитал документацию и ни разу не понял взаимосвязи. Пришлось попросить помощи у студента этого курса, который осознал эту сущность...

Структура приложения такова:

-5

Существует две директории: .venv (virtual environment) и app (само приложение). А так же несколько файлов: .gitignore - список расширений файлов которые не нужно загружать в git. example.csv - файл с именами, фамилиями и прочими данными студентов, которые нужно загружать в одном из заданий. readme.md - минимальное описание проекта. requirements.txt - список зависимостей, которые нужно установить для полноценной работы приложения.

__init__.py - файл в котором инициализируется Flask-приложение, прописывается подключение к базе данных postgres:

-6

Подключается файл views.py, в котором будут прописаны все конечные точки, примерно выглядит так:

-7

Подробней расскажу позже...

Файл run.py, который создает таблицы в базе данных и наполняет её какими-то минимальными данными, чтобы с ними можно было оперировать в дальнейшем:

-8

Итак, начнем с моделей. Каждую модель я упаковал в отдельный файл, и все модели упакованы в директорию models, верней, правильно назвать python-пакет, потому как присутствует файл __init__.py и он не пустой:

-9

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

Ну и по порядку, покажу все модели:

базовая модель, которая наследуется в последующих моделях. Зачем нужно __abstract__ = True, не знаю, откуда то выписал. Возможно будет всё работать и без этой строчки. Аннотации сделаны для сокращения кода здесь и в будущих моделях
базовая модель, которая наследуется в последующих моделях. Зачем нужно __abstract__ = True, не знаю, откуда то выписал. Возможно будет всё работать и без этой строчки. Аннотации сделаны для сокращения кода здесь и в будущих моделях
-11
-12

Самая сложная, для меня, модель - Student:

-13
Я так толком и не понял association_proxy, как это работает и что оно делает
Я так толком и не понял association_proxy, как это работает и что оно делает

И вытекающая из модели Student модель ReceivingBook:

-15
-16

Ещё раз повторюсь, с association_proxy я так и не разобрался, вроде бы сделано а понимания в голове не осталось...

Следующий файл - класс, который очищает все таблицы от имеющихся данных, создаёт таблицы и наполняет их данными. Он вызывается в файле run.py:

-17
-18
-19
-20
-21
-22

Ну вот, все модели прописаны, можно создавать эндпойнты для операций с данными. Всё происходит в файле views.py, это самый большой файл во всём проекте, вначале идут операции, которые были у меня в первой части SQLAlchemy:

-23
-24
-25
-26
-27
-28
-29

Далее идёт реализация энпойнтов, относящихся к заданию 21:

-30
-31
-32
-33
-34

Ну вот все эндпойнты описаны осталось две директории, в одной лежат статик-файлы (css, javascrip, jpg и прочие), в моём же случае это один лишь файл style.css, который делает таблицы более симпатичными.

-35

И последняя директория - templates, в которой находятся все html-файлы шаблонов куда передаётся контекст (данные, полученные и обработанные в формат json, из запроса к базе данных). Все файлы показывать не буду, они примерно идентичны этому:

-36

Результат выполнения данного HTML-кода:

-37

Ну вот, вроде бы и всё. С одной стороны банальная база данных с минимальным количеством таблиц, а с другой стороны я как-то очень долго въезжал в эту тему.

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