Курс по Django: https://stepik.org/a/183363
Архив проекта: 19_sitewomen.zip
На предыдущем
занятии мы с вами описали модель Women и создали на ее основе таблицу в БД,
используя механизм миграций. Теперь пришло время научиться работать с этой
таблицей, добавлять, выбирать, менять и удалять записи. По-английски все эти
операции сокращенно определяются аббревиатурой CRUD по первым
буквам английских слов:
- Create
– создание;
- Read
– чтение;
- Update
– изменение;
- Delete – удаление.
Используя ORM фреймворка Django, мы увидим, как
выполняются данные команды в базовом исполнении. Почти все проекты, построенные
на Django используют его
встроенную ORM, не переходя на
уровень SQL-запросов. В
этом часто просто нет необходимости, так как ORM предоставляет
богатейшие возможности по работе с БД. Кроме того, это обеспечивает
независимость программного кода от конкретной используемой СУБД и если в
будущем потребуется изменить тип БД, то сделать это будет предельно просто.
Наконец, ORM в Django хорошо
оптимизирует запросы по скорости выполнения и частоте обращения к таблицам БД, а
также обеспечивает защиту от SQL-инъекций. Благодаря этому, даже
начинающий веб-программист сможет создавать грамотный код по работе с БД.
На этом занятии
мы рассмотрим базовые операции с таблицами посредством ORM Django. Позже мы еще
углубимся в эту тему, а пока важно лишь понять общий принцип работы с моделями,
знать как добавлять, выбирать, изменять и удалять записи.
Итак, первое,
что нужно хорошо себе представлять, это то, что каждый экземпляр модели Women представляет
собой одну отдельную запись таблицы women_women (далее просто women).
То есть, когда
мы выбираем записи, или создаем новые записи, то происходит работа именно с
объектами класса Women. Сам же класс, как мы уже говорили,
описывает структуру (набор и тип полей) таблицы.
Для демонстрации
работы с ORM перейдем в консоль
Django и в терминале
выполним команду:
python manage.py
shell
чтобы войти в
консоль фреймворка. Первым делом выполним импорт модели:
from women.models import Women
Теперь, чтобы добавить
новую запись в таблицу, нам достаточно создать экземпляр класса Women и передать в
его конструктор значения именованных параметров, характеризующие поля таблицы:
Women(title='Анджелина Джоли', content='Биография Анджелины Джоли')
Мы видим, что
объект был создан, но при этом были указаны только два аргумента. Дело в том,
что атрибуты time_create и time_update у нас в модели инициализируются
автоматически и определять их конкретными значениями нет необходимости. Поле is_published
по умолчанию также принимает значение True. По идее, content тоже можно было
бы не определять (из-за параметра blank=True), но я захотел,
чтобы оно содержало короткую строку.
Если сейчас
перейти в SQLiteStudio и посмотреть
содержимое таблицы women_women, то никаких
записей не увидим. Почему так произошло? Дело в том, что модели в Django по умолчанию
являются «ленивыми», создание экземпляра класса еще не означает добавление
записи в таблицу. Как вы понимаете, это сделано специально. Мы можем в разных
местах программы создавать объекты моделей и только в последний момент
запускать их на исполнение, то есть, заносить информацию в БД. Благодаря этому Django имеет
возможность оптимизировать SQL-запросы и излишне не нагружать СУБД.
Хорошо, давайте
все же укажем фреймворку сохранить созданную запись в таблице. Для этого нам
понадобится какая-либо переменная, ссылающаяся на созданный объект, например,
такая:
Здесь символ ‘_’
– это специальная ссылка, в которой сохраняется результат последней операции. Если
вывести переменную w1, то увидим строку:
<Women: Women object (None)>
Здесь None – это номер id, который
принимает определенное, уникальное числовое значение в момент помещения записи
в таблицу. Это делается с помощью метода save():
и, выводя опять
же эту переменную в консоль, получаем строку:
<Women: Women
object (1)>
Видим, вместо None уже стоит
значение 1, то есть, запись была добавлена непосредственно в таблицу и ей был
присвоен идентификатор с номером 1. Перейдем в программу SQLiteStudio и убедимся, что
данные в таблице действительно появились. Да, это так, причем остальные поля
также были проинициализированы нужными значениями.
Непосредственно
в программе, то есть, в консоли Django мы можем оперировать всеми этими
данными через ссылку w1:
w1.id # идентификатор
w1.title # заголовок
w1.time_create # время добавления записи
и так по всем
полям (атрибутам класса). Помимо этих стандартных атрибутов объекты моделей
содержат еще один часто используемый атрибут:
w1.pk # значение primary key
который
совпадает с атрибутом id. Зачем было сделано такое дублирование?
Дело в том, что поле id в таблицах имеет важное значение: часто
именно по нему устанавливаются связи между таблицами. Поэтому по соглашению в Django решили
определить атрибут со строго определенным именем pk, который будет
всегда доступен и содержать номер текущей записи, либо значение None, если оно не
определено. Позже мы не раз будем обращаться к этому свойству, как к
идентификатору записи.
Конечно, непосредственное
добавление записи в таблицу выполнялось с помощью SQL-запроса к БД. Чтобы
его увидеть, нам нужно сначала импортировать модуль connection:
from django.db import connection
и обратиться к
коллекции queries:
В консоли появится
список словарей из выполненных запросов. У этого словаря имеются два ключа: sql – текст SQL-запроса; time – время выполнения
этого запроса.
Давайте для
примера создадим еще одну запись:
w2 = Women(title='Энн Хэтэуэй', content='Биография Энн Хэтэуэй')
Список queries
остался прежним, так как запись еще не была добавлена в таблицу. Выполним
команду:
Теперь в списке queries
два запроса, а в таблице две записи. Эти два последних примера показывают, что
объект класса Women можно наполнять
информацией как угодно до момента непосредственной записи. Например, можно
вначале создать экземпляр класса без аргументов:
а, затем, его локальным
атрибутам присвоить требуемые значения:
w3.title = 'Джулия Робертс'
w3.content = 'Биография Джулии Робертс'
После вызова
метода save, запись будет
добавлена в таблицу:
Установка улучшенной консоли ipython
Обратите внимание,
что консоль фреймворка Django не очень удобна в работе, она
даже не подсказывает нам возможные варианты команд, модулей и тому подобное. Но
ее достаточно легко можно улучшить, установив специальный пакет ipython. Для этого в PyCharm
перейдем
в меню:
File->Settings
И в появившемся окне выберем Project:sitewomen->Python Interpreter. Нажмем на «плюс»
и в строке поиска наберем ipython. Нажмем на кнопку «Install Package». Пакет будет
установлен для текущего выбранного интерпретатора.
Запустим снова
консоль фреймворка Django командой:
python manage.py
shell
и увидим
несколько другое оформление. Но что изменилось в функциональности? Смотрите,
если теперь начать вводить какую либо команду, например:
fr
и нажать на
кнопку Tab, то увидим
возможные варианты. Последующие нажатия на Tab будут
подставлять соответствующие команды. Наберем:
from women.models import Women
Видите, как это
стало проще и удобнее? Выйдем из консоли с помощью команды exit.
Установка улучшенной пакета django-extensions
В заключение
этого занятия давайте установим еще один пакет, который может упростить
отработку ORM-команд в
консоли. Он называется django-extensions и
устанавливается аналогично предыдущему пакету:
https://github.com/django-extensions/django-extensions
После установки
согласно документации мы должны его прописать в коллекции INSTALLED_APPS файла
конфигурации settings.py. Сделаем это:
INSTALLED_APPS = [
...
'django_extensions',
'women.apps.WomenConfig',
]
После этого, нам
становится доступна новая команда shell_plus, которую
выполним с ключом --print-sql:
python manage.py
shell_plus --print-sql
Запустится новая
оболочка с поддержкой ранее установленного ipython и с
автоматической распечаткой выполняемых SQL-запросов.
Давайте в этом убедимся. Создадим объект класса Women (в оболочке shell_plus модели
импортируются автоматически):
a = Women(title="Екатерина Гусева", content="Биография Екатерины Гусевой")
и вызовем метод save():
В результате нам
автоматически выводится SQL-запрос, который добавил эту запись в
БД. И это гораздо удобнее, чем каждый раз смотреть его в коллекции queries модуля connection.
Курс по Django: https://stepik.org/a/183363