Что такое django orm

Django ORM, gevent и грабли в зелени

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

Gevent тоже выбирают из-за того, что он простой, очень шустрый и не несёт за собой callback hell.

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

Django ORM и пул соединений БД

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

Возьмём простой пример, который имитирует бурную деятельность с HTTP-запросами. Пусть это будет сервис для сокращения ссылок:

Без gevent этот код работал бы невероятно медленно и с трудом обслуживал бы два-три одновременных запроса, но с gevent всё летает.

Запускаем наш проект через uwsgi (который де-факто стал стандартом при деплое Python-сайтов:

Пробуем тестировать десять запросов на сокращение ссылки одновременно и радуемся: все запросы отрабатывают без ошибок за минимальное время.

Запускаем наш новый сервис, сидим и смотрим на его успешное развитие. Нагрузка растёт с 10 до 75 одновременных запросов, и ему такая нагрузка нипочём.

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

И это хорошо, если вы поставили локаль en_US.UTF-8 в postgresql.conf, потому что если вы использовали конфигурацию Ubuntu/Debian по умолчанию, то вы получите тысячу писем с сообщением вида:

Приложение создавало слишком много соединений с базой данных (по умолчанию — максимум 100 соединений), за что и было наказано.

Вот и самый первый подводный камень: в Django нет пула соединений с базой данных, потому что в синхронном коде он попросту не нужен. Один синхронный процесс Django не может обрабатывать запросы параллельно, он в любой момент времени обслуживает только один запрос, и поэтому у него не возникает надобности в создании более чем одного соединения с базой данных.

Решение одно: нам срочно нужен пул соединений с БД.

Реализаций пула для Django сравнительно немного, например django-db-pool и django-psycopg2-pool. Первый пул основан на psycopg2.TreadedConnectionPool, который бросает исключение при попытке взять соединение из пустого пула. Приложение будет вести себя так же, как и раньше, но при этом другие приложения смогут создать соединение с БД. Второй пул основан на gevent.Queue: при попытке взять соединение из пустого пула гринлет будет заблокирован до тех пор, пока другой гринлет не положит соединение в пул.
Скорее всего вы выберете второе решение как более логичное.

Запросы к БД внутри гринлетов

Мы уже пропатчили приложение с помощью gevent и нам мало синхронных вызовов, так почему бы не выжать максимум из гринлетов? Мы можем параллельно делать несколько HTTP-запросов или создавать подпроцессы. Возможно, нам захочется использовать БД в гринлетах:

Прошло несколько часов, и вдруг наше приложение полностью перестало работать: на любой запрос получаем 504 Gateway Timeout. Что на этот раз случилось? За разъяснением придётся почитать немного кода Django.

Источник

Django ORM для начинающих | Оптимизируем запросы

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

Django ORM (Object Relational Mapping) является одной из самых мощных особенностей Django. Это позволяет нам взаимодействовать с базой данных, используя код Python, а не SQL.
Based on schegel.net

Для демонстрации опишу такую модель:

Я буду использовать django-extentions, чтобы получить полезную информацию с помощью:

1. Используем ForeignKey значения непосредственно

А так получаем 1 запрос в БД:

2. OneToMany Relations

Если мы используем OneToMany отношения мы используем ForeignKey поля и запрос выглядит примерно так:

И если мы хотим получить доступ к объекту блога из объекта поста, мы можем сделать:

Тем не менее, это вызвало новый запрос, чтобы получить информацию из блога. Так что используйте select_related, чтобы избежать этого. Чтобы использовать его, мы можем обновить наш оригинальный запрос:

Обратите внимание, что Django использует JOIN сейчас! И время выполнения запроса меньше, чем раньше. Кроме того, теперь post.blog будет кэширован!

select_related так же работает с QurySets:

3. ManyToMany Relations

Чтобы получить авторов постов мы используем что-то вроде этого:

Похоже, мы получили запрос для каждого объекта поста. По этому, мы должны использовать prefetch_related. Это похоже на select_related но используется с ManyToMany Fields:

Что только что произошло. Мы сократили количество запросов с 2 до 1, чтобы получить 2 QuerySet-a!

4. Prefetch object

prefetch_related достаточно для большинства случаев, но это не всегда помогает избежать дополнительных запросовю К примеру, если мы используем фильтрацию Django не может использовать наши кэшированные posts, так как они не были отфильтрованы, когда они были запрошены в первом запросе. И мы получим:

То есть, мы использовали prefetch_related, чтобы уменьшить количество запросов, но мы фактически увеличили его. Чтобы этого избежать, мы можем настроить запрос с помощью объекта Prefetch:

Мы использовали определенный запрос для получения постов через параметр запроса и сохранили отфильтрованные сообщения в новом атрибуте. Как мы видим, теперь у нас есть только 2 запроса в базу данных.

Источник

Основы ORM Django за час

На этом занятии мы рассмотрим основные команды ORM Django (иногда еще говорят API модели). Это будет лишь обзорное занятие огромной темы. Если вы уже знакомы с ORM, то можно пропустить его и переходить к следующим темам. Для всех остальных – это введение, чтобы у вас сформировалось начальное представление об использовании этого API.

Некоторое введение у нас уже было, когда мы рассматривали операции для одной конкретной модели (таблицы). Здесь же углубимся в эту тему и посмотрим, как можно выполнять манипуляции со связанными таблицами. В качестве примера у нас будет две наших ранее созданных модели: Women и Category, которые связаны по внешнему ключу:

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

Вообще, ORM Django имеет очень богатый функционал и вам вряд ли понадобится переходить на уровень SQL-запросов, все можно сделать на уровне этого API. Кроме того, начинающим разработчикам уровень ORM позволит писать грамотные и оптимизированные запросы к БД любого типа: SQLite, MySQL, PostgreSQL, Oracle, то есть, приложение будет совершенно независимым от типа СУБД. Все это и привело к тому, что сейчас, в основном, используются различные ORM при работе с таблицами БД. Подробную информацию обо всем этом можно посмотреть на сайте русскоязычной документации:

в разделе «ORM и работа с базой данных» и подразделе «QuerySet». В частности ссылка «методы QuerySet»:

приводит нас на страницу с описанием различных методов, которые доступны в ORM Django. Как всегда, советую с ними подробно ознакомиться, чтобы грамотно их использовать в своих проектах. Чаще всего используются методы: filter, all, get, о которых мы уже немного говорили. Также здесь вы найдете, так называемые, lookup’ы, которые позволяют формировать различные условия для выборки записей, и ниже представлены функции агрегации.

Чтобы демонстрировать работу команд, я перейду в терминал и запущу оболочку Django:

python manage.py shell

Первой строчкой импортирую модели, с которыми будем работать:

Давайте проверим, все ли работает корректно. Выполним уже знакомую нам команду для выборки всех записей из таблицы women:

Мы видим список, порядок сортировки которого определен в классе Meta класса модели Women. Если нужно отобрать не все записи, а лишь некоторые из них, то можно использовать синтаксис срезов, чтобы Django указать сделать это, например, так:

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

то в конце последнего запроса увидим фрагмент «LIMIT 5». А при выполнении такой команды:

получим в запросе «LIMIT 5 OFFSET 3». То есть, здесь везде делается отбор на уровне SQL-запросов, что очень эффективно.

Далее, если нужно поменять порядок и отсортировать записи по определенному полю, то используется метод order_by():

В данном случае мы сортируем записи по их идентификатору. Почему здесь используется имя поля pk, а не id? Как я уже отмечал, по соглашению в Django имя pk по умолчанию используется для обращения к первичному ключу, так как это поле в таблице мы могли бы назвать не id, а как то иначе. Чтобы сделать его название универсальным на уровне ORM, Django и использует это имя pk.

Сразу же здесь напомню, что символ минус перед именем поля означает обратный порядок сортировки:

Также порядок (на противоположный) можно менять с помощью метода reverse():

Он удобен, если формируется некая выборка и нам нужно просто поменять порядок следования записей на противоположный. Здесь уже нет необходимости указывать конкретное поле, а просто записать reverse().

На одном из прошлых занятий я вам приводил пример метода filter() для выбора нескольких записей по некоторому условию:

и метод get() для получения строго одной записи:

Но не сказал, что filter() всегда возвращает записи в виде списка, а get() – в виде одного объекта (экземпляра модели). Обычно, метод get() необходим для выбора строго одной записи и для этого использую или поле pk, или поле slug (они оба создаются как уникальные).

Давайте теперь посмотрим, как происходит обработка связанных данных. Сохраним объект какой-либо записи в переменной w:

Давайте, для примера, выполним строчку, чтобы убедиться, что cat – это действительно ссылка на экземпляр класса Category:

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

получим название категории. Причем, получение конкретных связанных данных происходит только в момент обращения к ним. В данном случае в строчке w.cat Django автоматически сгенерировал запрос к таблице category и взял запись с Таким образом, мы увидели как вторичная модель Women связывается с первичной моделью Category и получает соответствующие данные.

Но можно сделать и наоборот, используя первичную модель Category получить все связанные с ней посты из вторичной модели Women. Для этого у любой первичной модели по умолчанию автоматически создается специальное свойство (объект) с именем:

И уже с его помощью можно выбирать связанные записи. Давайте сделаем это. Сначала прочитаем запись из таблицы category, например, с >

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

Если мы хотим переименовать атрибут women_set, то для этого в классе ForeignKey вторичной модели Women следует дополнительно прописать параметр:

Здесь get_posts – это новое имя атрибута для обратного связывания. Чтобы изменения вступили в силу, нужно выйти из оболочки Django, снова зайти, импортировать модели, прочитать категорию и отобразить связанные посты с уже новым именем атрибута:

Разумеется, вместо метода all() мы можем использовать и другие уже известные нам методы, например, filter():

(Убираем параметр related_name и перезапускаем оболочку).

Фильтры полей

Рассмотрим еще несколько интересных примеров lookups. Фильтр contains позволяет находить строки по их фрагменту, учитывая регистр букв. Например, вот такая команда:

выдаст список всех женщин, в заголовке у которых присутствует фрагмент «ли». Опять же, на уровне SQL-запроса это делается с помощью фрагмента:

«WHERE title LIKE ‘%ли%’»

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

то получим пустой список. Почему? Дело в том, что СУБД SQLite не поддерживает регистронезависимый поиск для русских символов (вообще, для всех не ASCII-символов), поэтому получаем пустой список. Другие СУБД, как правило, отрабатывают все это корректно. В случае с латинскими символами в SQLite поиск всегда проходит как регистронезависимый.

Следующий полезный фильтр in позволяет указывать через список выбираемые записи по значениям. Например, выберем записи с id равными 2, 5, 11, 12:

Если по условию нужно отработать сразу несколько фильтров, то они указываются через запятую:

Теперь мы видим всего две записи, так как посты с id 11 и 12 отмечены как неопубликованные. Причем, обратите внимание, указывая два критерия через запятую, на уровне SQL-запросов формируется связка через AND (логическое И):

WHERE («women_women».»is_published» AND «women_women».»id» IN (2, 5, 11, 12))

то есть, запись выбирается, если оба критерия срабатывают одновременно. Чтобы определять условия через OR (логическое ИЛИ) используется специальный класс Q. Речь о нем пойдет дальше.

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

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

а, затем, подставить их вместо списка:

По аналогии используются и все остальные фильтры фреймворка Django.

Использование класса Q

— логическое НЕ (приоритет 1).

Давайте посмотрим, как это все работает. Вначале его нужно импортировать:

Теперь, смотрите, если выполнить вот такой запрос:

то на выходе получим пустой список, т.к. все записи с id =5 или cat_id=2.

Вот так можно использовать класс Q для описания запросов с использованием операторов &, | и

. И всегда помните о приоритетах операций: сначала выполняется НЕ, затем, И и в последнюю очередь ИЛИ.

Методы выбора записей

В ORM Django есть несколько полезных методов для быстрого получения определенных записей из таблицы. Например, чтобы взять первую запись из выборки, используется метод first():

Мы в этом можем убедиться, если выведем все посты:

То есть, берется первая запись в соответствии с порядком сортировки модели. Мы можем поменять этот порядок и с помощью этого же метода first() выбирать разные записи, например, так:

Или же воспользоваться методом last() для выбора последней записи из набора:

Методы latest и earliest

Для чего могут понадобиться такие методы? Например, сделана выборка с сортировкой по какому-либо другому полю (не time_update) и из этой выборки нужно получить самую раннюю или самую позднюю запись:

Методы get_previous_by_, get_next_by_

Если нужно выбрать предыдущую или следующую запись относительно текущей, то в ORM для этого существует два специальных метода, которые выбирают записи опять же по указанному полю с датой и временем. Например, мы выбираем некую запись с pk=7:

Тогда, для получения предыдущей записи относительно текущей, можно записать:

Здесь суффикс time_update – это название поля, по которому определяется предыдущая запись. То есть, здесь используется не порядок следования записей в выборке, а временное поле. И уже по нему смотрится предыдущая или следующая запись:

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

выбирается следующая запись с id больше 10.

Методы exists и count

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

Давайте я добавлю в таблицу Category еще одну рубрику «Спортсменки» и эта рубрика пока у нас пуста, то есть, нет ни одной записи с ней связанной. Как вы уже догадались, мы сейчас протестируем метод exists(), который возвращает True, если записи есть и False – в противном случае.

Увидим False, а для второй категории:

получим значение True. Соответственно, вызывая второй метод, можем получить число записей:

То есть, методы exists() и count() применяются к любой выборке.

Выборка записей по полям связанных моделей

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

Как это работает? В действительности, вот этот параметр cat__slug сформирован по следующему правилу:

То есть, здесь мы обращаемся к первичной модели через атрибут cat, который прописан во вторичной модели Women, а затем, через два подчеркивания указываем имя поля тоже первичной модели, по которому отбираются записи уже вторичной модели. И на выходе получаем список постов для актрис.

Этот синтаксис немного похож на использование фильтра in:

Только здесь вместо указания списка идентификаторов рубрик, используется слаг с определенным названием. Во всем остальном принцип работы идентичен.

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

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

Конечно, это несколько странный, искусственный пример, но он хорошо показывает принцип использования фильтров для полей первичной модели. Если уточнить этот фильтр:

то получим уже записи только по певицам. Или сделать наоборот, выбрать все категории, которые связаны с записями вторичной модели Women, содержащие в заголовке фрагмент строки «ли»:

Обратите внимание, на выходе получим набор из нескольких повторяющихся категорий, каждая из которых соответствует определенной записи из модели Women. Если нужно отобрать только уникальные записи (категории), то дополнительно следует указать метод distinct():

Агрегирующие функции

Далее, мы с вами рассмотрим несколько агрегирующих методов. С одним из них, мы в принципе, уже знакомы – это метод count(), который подсчитывает число записей. В самом простом случае, с его помощью можно определить число записей в таблице women:

Подробно о том, что такое агрегация на уровне SQL-запросов, я уже рассказывал на занятии по SQLite и, если вы мало знакомы с этой информацией, то дополнительно советую посмотреть и это видео:

Остальные агрегирующие команды обычно прописываются в специальном методе aggregate(), например:

Но, чтобы ими воспользоваться, нужно их импортировать:

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

На выходе получим следующий словарь:

Если по каким-либо причинам стандартные ключи нам не подходят, и мы бы хотели их поменять, то делается это так:

С агрегирующими значениями можно выполнять различные математические операции, например:

По аналогии используются все остальные агрегирующие операции:

Здесь агрегация выполняется не для всех записей, а только для тех, у которых id больше 4.

Метод values

Во всех наших примерах выше, при выборке записей автоматически возвращались все поля. Если это была таблица women, то получали девять полей от id до cat_id. Но часто этого не требуется и достаточно ограничится несколькими нужными полями. Кроме того, такое ограничение положительно сказывается на скорости обращения к БД.

Итак, для указания нужных полей в выборке, используется метод values() с указанием названий полей, например, так:

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

то Django сформирует запрос с использованием оператора JOIN SQL-запроса. Если посмотреть коллекцию:

то увидим следующее:

SELECT «women_women».»title», «women_category».»name» FROM «women_women» INNER JOIN «women_category» ON («women_women».»cat_id» = «women_category».»id») WHERE «women_women».»id» = 1 LIMIT 21

Благодаря такой конструкции одним запросом выбираются все нужные данные. Или, даже так:

При выполнении этой строчки пока ни один SQL-запрос выполнен не был, т.к. запросы в Django «ленивые», обращение к БД происходит только в момент получения данных. Но, если вывести список постов:

то увидим, что для этой операции также был сделан всего один запрос. То есть, Django достаточно хорошо оптимизирует процесс обращения к БД.

Группировка записей и агрегирование через метод annotate

Часто вызов агрегирующих функций применяется не ко всем записям, а к группам, сформированным по определенному полю. Например, в таблице Women можно сгруппировать записи по cat_id и получим две независимые группы записей. Затем, к каждой группе применить агрегацию и получить искомые значения.

В качестве примера, давайте подсчитаем число постов для каждой группы категорий. Для этого запишем такую команду:

Ее действие графически можно представить так:

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

То есть, здесь группировка автоматически выполняется по единственному полю, которое мы выбираем из таблицы. Однако, выполняя ее, мы не видим ожидаемого результата. Почему? Если посмотреть последний SQL-запрос:

то увидим, что группировка также выполняется по полям title и time_create. Это связано с тем, что в модели Women во вложенном классе Meta прописана сортировка по этим полям:

Поставим эту строчку в комментарий, выйдем из оболочки Django, снова зайдем, импортируем необходимые модули:

и повторим команду:

Теперь видим две группы и для каждой подсчитано число статей. Мы можем изменить имя параметра id__count, скажем, на total, указав этот именной параметр:

Вот так можно группировать записи и вызывать для них с помощью метода annotate() нужную агрегатную функцию.

Вообще, метод annotate() используется для вызова агрегирующих функций в пределах групп. Если не указывать никаких полей для группировки:

То получим просто все записи (так как группировка будет выполняться для всех полей). А вот если записать наоборот:

то также получим все рубрики, но в каждом объекте списка будет атрибут:

содержащий число записей для текущей рубрики. Мало того, далее, мы можем прописывать другие методы, для отбора этих рубрик по значению агрегатной функции:

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

Класс F

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

Но что если вместо 2 нужно прописать значение другого поля таблицы? Просто указать его не получится, например, такая запись:

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

И, далее, вместо двойки запишем класс F, допустим, с полем cat_id:

Получим все записи, кроме первой (с А SQL-запрос будет иметь вид:

SELECT … FROM «women_women» WHERE «women_women».»id» > «women_women».»cat_id»

Здесь условие «id > cat_id» как раз и было сформировано благодаря использованию F класса.

Конечно, это такой искусственный пример, демонстрирующий работу F-класса. Часто подобные операции приходится делать, когда нужно увеличить, например, счетчик просмотра страниц. Если предположить, что в нашей таблице women есть поле views для числа просмотров, то при каждом посещении страницы, мы могли бы увеличивать его значение на 1, следующим образом:

При посещении страницы со слагом ‘bejonse’ произойдет увеличение ее считчика на 1.

Или, бывает удобно делать так. Сначала статья читается из таблицы (мы ее так и так должны отображать на HTML-странице):

А, затем, происходит изменение счетчика:

После сохранения, новое значение будет записано в таблицу БД.

У вас здесь может возникнуть вопрос: а почему бы нам в данном случае не использовать операцию инкремента:

Скорее всего, так тоже сработает, но в документации по Django такой подход не рекомендуется. Здесь могут возникать неопределенности при одновременном получении одной и той же страницы разными пользователями. Тогда значение views будет увеличено только один раз, хотя просмотров было два. Класс F решает подобные коллизии.

Организация вычислений на уровне СУБД

Фреймворк Django содержит набор функций, позволяющие выполнять вычисления, связанные с полями таблицы, на стороне СУБД. Полный их список можно посмотреть по ссылке:

Фактически, здесь приведены обертки над функциями, которые выполняются СУБД. Этих функций достаточно много. Это и функции работы со строками, датой, математические функции и так далее. Использование этих функций является рекомендуемой практикой, т.к. СУБД оптимизировано для их выполнения. Конечно, все имеет свои разумные пределы и нужно лишь по необходимости прибегать к этому функционалу.

Давайте для примера рассмотрим использование функции Length для вычисления длины строки. Первым делом нам нужно ее импортировать:

И, затем, аннотируем новое вычисляемое поле, например, для заголовков статей:

В результате, на ряду со всеми стандартными полями, получим дополнительное поле len:

По аналогии используются все остальные подобные функции.

Raw SQL

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

В простейшем варианте выполнить непосредственно SQL-запрос можно через метод:

На выходе получаем объект RawQuerySet, содержащий данные выборки. Давайте выведем ее в консоль через цикл for:

Как видите, все достаточно просто. Причем, абсолютно тот же самый результат увидим и при использовании класса модели Category:

Здесь модель не имеет особого значения, мы с ее помощью просто обращаемся к менеджеру записей (objects), чтобы выполнить метод raw() для запуска SQL-запроса. Хотя сами объекты в списке w будут являться уже экземплярами класса Category. Поэтому, для обращения к таблице women лучше использовать модель Women.

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

Однако, метод raw() имеет несколько нюансов в своей работе. Первый из них – это «ленивое» исполнение запроса, то есть, отложенная загрузка информации до момента первого обращения к ней. Например, при выполнении команды:

никакого SQL-запроса выполнено не будет. До тех пор, пока мы не попытаемся что-либо прочитать из переменной w:

увидим один выполненный запрос:

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

Без id метод raw() выдаст исключение. Также, смотрите, несмотря на то, что мы указали в SELECT всего два поля, мы, тем не менее, через ссылку w можем обратиться к любому другому, например, так:

Здесь сработал механизм отложенной загрузки полей и при обращении к конкретному, не указанному ранее полю, происходит дополнительное обращение к БД для его получения. И, действительно, в списке запросов мы видим это:

SELECT «women_women».»id», «women_women».»is_published» FROM «women_women» WHERE «women_women».»id» = 1

Как вы понимаете, это не лучшая практика и такого нужно избегать. Если у вас много постов и вы для каждого поля is_published будете так выбирать данные, то Django сгенерирует множество одиночных SQL-запросов для их чтения. Это может заметно и необоснованно нагрузить используемую СУБД.

Следующий момент – это возможность передавать параметры в SQL-запрос. Например, если мы хотим выбрать запись по ее слагу, то нужно написать что-то вроде:

Но здесь вместо ‘shakira’, обычно, используется некий параметр, в котором и хранится значение слага. Конечно, первое что приходит на ум, это объявить некую переменную:

и напрямую передать ее в SQL-запрос:

Однако, это прямой путь к SQL-инъекциям, когда злоумышленник вместо слага запишет фрагмент SQL-запроса и прочитает данные из БД. Поэтому правильно будет использовать механизм параметров в таких raw-запросах:

Соответственно, в списке параметров можно указывать множество переменных и прописывать их в SQL-запросе.

На этом мы завершим обзор этой объемной темы – ORM Django. Конечно, здесь я вам показывал лишь принцип использовать различных методов и рассказывал о нюансах их работы. Объять этот материал целиком – слишком амбициозная задача, да и напоминать такие занятия будут справочное руководство. В конце концов, для этого есть документация – наше все. Без нее при изучении и дальнейшем использовании Django – никуда. Ссылки на нее будут под этим видео.

Видео по теме

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#2. Модель MTV. Маршрутизация. Функции представления

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#3. Маршрутизация, обработка исключений запросов, перенаправления

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#4. Определение моделей. Миграции: создание и выполнение

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#6. Шаблоны (templates). Начало

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#7. Подключение статических файлов. Фильтры шаблонов

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#8. Формирование URL-адресов в шаблонах

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#9. Создание связей между моделями через класс ForeignKey

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#10. Начинаем работу с админ-панелью

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#11. Пользовательские теги шаблонов

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#12. Добавляем слаги (slug) к URL-адресам

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#13. Использование форм, не связанных с моделями

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#14. Формы, связанные с моделями. Пользовательские валидаторы

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#15. Классы представлений: ListView, DetailView, CreateView

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#16. Основы ORM Django за час

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#18. Постраничная навигация (пагинация)

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#19. Регистрация пользователей на сайте

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#20. Делаем авторизацию пользователей на сайте

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#21. Оптимизация сайта с Django Debug Toolbar

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#22. Включаем кэширование данных

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#23. Использование капчи captcha

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#24. Тонкая настройка админ панели

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#25. Начинаем развертывание Django-сайта на хостинге

Что такое django orm. Смотреть фото Что такое django orm. Смотреть картинку Что такое django orm. Картинка про Что такое django orm. Фото Что такое django orm

#26. Завершаем развертывание Django-сайта на хостинге

© 2021 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *