Мэтиз. Изучаем Python. Crash course2 n d e d i t i o na h a n d s o n, p r o j e c t b a s e d i n t r o d u c t i o n t o p r o g r a m m i n g
Скачать 6.2 Mb.
|
python manage.py makemigrations learning_logs Migrations for 'learning_logs': ❶ learning_logs/migrations/0002_entry.py - Create model Entry (ll_env)learning_log$ python manage.py migrate Operations to perform: ❷ Applying learning_logs.0002_entry... OK Команда генерирует новую миграцию с именем 0002_entry .py , которая сообщает Django, как изменить базу данных для хранения информации, связанной с мо делью 406 Глава 18 • Знакомство с Django Entry . При выдаче команды migrate Django подтверждает, что применение ми- грации прошло успешно . Регистрация Entry на административном сайте Модель Entry тоже необходимо зарегистрировать. Файл admin .py должен выглядеть так: admin.py from django.contrib import admin from .models import Topic, Entry admin.site.register(Topic) admin.site.register(Entry) Вернитесь на страницу http://localhost/admin/ , и вы увидите раздел Entries в кате- гории learning_logs . Щелкните на ссылке Add для Entries или щелкните на Entries и выберите вариант Add . На экране появляется раскрывающийся список для выбора темы, для которой создается запись, и текстовое поле для ввода записи. Выберите в раскрывающемся списке вариант Chess и добавьте запись. При выборе ссылки Save вы вернетесь к основной административной странице. Здесь проявляются преимущества использования формата text[:50] в качестве строкового представления каждой записи; работать с несколькими записями в ад- министративном интерфейсе намного удобнее, если вы видите только часть записи вместо ее полного текста. Создайте вторую запись для темы Chess и одну запись для темы Rock Climbing , чтобы у нас были исходные данные для дальнейшей разработки Learning Log. Интерактивная оболочка Django Введенные данные можно проанализировать на программном уровне в интерактив- ном терминальном сеансе. Эта интерактивная среда, называемая оболочкой (shell) Django, прекрасно подходит для тестирования и диагностики проекта. Пример сеанса в интерактивной оболочке: (ll_env)learning_log$ python manage.py shell ❶ >>> from learning_logs.models import Topic >>> Topic.objects.all() Команда python manage.py shell (выполняемая в активной виртуальной среде) запускает интерпретатор Python, который может использоваться для работы с ин- формацией в базе данных проекта. В данном случае мы импортируем модель Topic из модуля learning_logs.models . Затем метод Topic.objects.all() используется Начало работы над приложением 407 для получения всех экземпляров модели Topic ; возвращаемый список называется итоговым набором (queryset). Содержимое итогового набора перебирается точно так же, как и содержимое спи- ска. Например, просмотр идентификаторов, назначенных каждому объекту темы, выполняется так: >>> topics = Topic.objects.all() >>> for topic in topics: ... print(topic.id, topic) 1 Chess 2 Rock Climbing Итоговый набор сохраняется в topics , после чего выводится атрибут id каждого объекта topic и его строковое представление. Мы видим, что теме Chess присвоен идентификатор 1, а Rock Climbing присвоен идентификатор 2. Зная идентификатор конкретного объекта, можно при помощи метода Topic. objects.get() получить этот объект и проанализировать содержащиеся в нем атрибуты. Просмотрим значения text и date_added для темы Chess : >>> t = Topic.objects.get(id=1) >>> t.text 'Chess' >>> t.date_added datetime.datetime(2019, 2, 19, 1, 55, 31, 98500, tzinfo= Также можно просмотреть записи, относящиеся к конкретной теме. Ранее мы определили атрибут topic для модели Entry . Он был экземпляром ForeighKey , представляющим связь между записью и темой. Django может использовать эту свзяь для получения всех записей, относящихся к некоторой теме: ❶ >>> t.entry_set.all() Чтобы получить данные через отношение внешнего ключа, воспользуйтесь именем связанной модели, записанным в нижнем регистре, за которым следует символ подчеркивания и слово set . Допустим, у вас имеются модели Pizza и Topping и модель Topping связана с Pizza через внешний ключ. Если ваш объект называется my_pizza , для получения всех связанных с ним экземпляров Topping используется выражение my_pizza.topping_set.all() Мы будем использовать такой синтаксис при переходе к программированию стра- ниц, которые могут запрашиваться пользователями. Оболочка очень удобна тогда, когда вы хотите проверить, что ваш код получает нужные данные. Если в оболочке код работает так, как задумано, можно ожидать, что он будет правильно работать и в файлах, которые вы создаете в своем проекте. Если код выдает ошибки или не 408 Глава 18 • Знакомство с Django загружает те данные, которые должен загружать, вам будет намного проще отладить его в простой оболочке, чем при работе с файлами, генерирующими веб-страницы. В книге мы не будем часто возвращаться к оболочке, но вам не стоит забывать о ней — это полезный инструмент, который поможет вам освоить синтаксис Django для работы с данными проекта. ПРИМЕЧАНИЕ При каждом изменении модели необходимо перезапустить оболочку, чтобы увидеть результаты этих изменений . Чтобы завершить сеанс работы с оболочкой, нажмите Сtrl+D ; в Windows нажмите Ctrl+Z , а затем Enter . УПРАЖНЕНИЯ 18.2. Короткие записи: метод __str__() в модели Entry в настоящее время присоединя- ет многоточие к каждому экземпляру Entry, отображаемому Django на административном сайте или в оболочке. Добавьте в метод __str__() команду if , добавляющую многоточие только для записей, длина которых превышает 50 символов. Воспользуйтесь администра- тивным сайтом, чтобы ввести запись длиной менее 50 символов, и убедитесь в том, что при ее просмотре многоточие не отображается. 18.3. Django API: при написании кода для работы с данными проекта вы создаете за- прос. Просмотрите документацию по созданию запросов к данным по адресу https://docs . djangoproject .com/en/2 .2/topics/db/queries/ . Многое из того, что вы увидите, покажется вам новым, но эта информация пригодится, когда вы начнете работать над собственными про- ектами. 18.4. Пиццерия: создайте новый проект с именем pizzeria , содержащий приложение pizzas . Определите модель Pizza с полем name , в котором хранятся названия видов пиццы (например, «Гавайская» или «Четыре сыра»). Определите модель Topping с полями pizza и name . Поле pizza должно содержать внешний ключ к модели Pizza , а поле name должно позволять хранить такие значения, как «ананас» или «грибы». Зарегистрируйте обе модели на административном сайте. Используйте сайт для ввода на- званий пиццы и топпингов. Изучите введенные данные в интерактивной оболочке. Создание страниц: домашняя страница Learning Log Обычно процесс создания веб-страниц в Django состоит из трех стадий: опреде- ления URL, написания представлений и написания шаблонов. Сначала следует определить схемы (patterns) URL. Схема URL описывает структуру URL-адреса и сообщает Django, на какие компоненты следует обращать внимание при сопо- ставлении запроса браузера с URL-адресом на сайте, чтобы выбрать возвращаемую страницу. Затем каждый URL-адрес связывается с конкретным представлением — функция представление читает и обрабатывает данные, необходимые странице. Функция представления часто вызывает шаблон, который строит страницу, подходящую для передачи браузеру. Чтобы вы лучше поняли, как работает этот механизм, создадим домашнюю страницу для приложения Learning Log. Мы определим URL-адрес домашней страницы, напишем для него функцию представления и создадим про- стой шаблон. Начало работы над приложением 409 Так как мы сейчас всего лишь убеждаемся в том, что Learning Log работает как по- ложено, страница пока останется простой. Когда приложение будет завершено, вы можете заниматься его оформлением сколько душе угодно; приложение, которое хорошо выглядит, но не работает, бессмысленно. Пока на домашней странице будет отображаться только заголовок и краткое описание. Сопоставление URL Пользователь запрашивает страницы, вводя URL-адреса в браузере и щелкая на ссылках, поэтому мы должны решить, какие URL-адреса понадобятся в нашем проекте. Начнем с URL домашней страницы: это базовый адрес, используемый для обращения к проекту. На данный момент базовый URL-адрес http://localhost:8000/ возвращает сайт, сгенерированный Django по умолчанию; он сообщает о том, что проект был создан успешно. Мы изменим домашнюю страницу, связав базовый URL-адрес с домашней страницей Learning Log. В каталоге проекта learning_log откройте файл urls .py . Вы увидите в нем следу- ющий код: urls.py ❶ from django.contrib import admin from django.urls import path ❷ urlpatterns = [ ❸ path('admin/', admin.site.urls), ] Первые две строки импортируют функции и модули, управляющие URL-адресами проекта и административным сайтом . В теле файла определяется переменная urlpatterns . В файле urls .py , представляющем проект в целом, переменная urlpatterns включает наборы URL-адресов из приложений в проект. Код включает модуль admin.site.urls , определяющий все URL-адреса, которые могут запрашиваться с административного сайта. Добавим в этот файл URL-адреса learning_logs : from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), ❶ path('', include('learning_logs.urls')), ] В точке добавляется строка включения модуля learning_logs.urls Файл urls .py по умолчанию находится в каталоге learning_log ; теперь нужно создать второй файл urls .py в папке learning_logs . Создайте новый файл Python, сохраните его под именем urls .py в learning_logs и включите в него следующий код: 410 Глава 18 • Знакомство с Django urls.py ❶ """Определяет схемы URL для learning_logs.""" ❷ from django.urls import path ❸ from . import views ❹ app_name = 'learning_logs' ❺ urlpatterns = [ # Домашняя страница ❻ path('', views.index, name='index'), ] Чтобы было понятно, с какой версией urls .py мы работаем, в начало файла добавля- ется строка документации . Затем импортируется функция path , она необходима для связывания URL с представлениями . Также импортируется модуль views ; точка приказывает Python импортировать представления из каталога, в котором находится текущий модуль urls .py . Переменная app_name помогает Django отличить этот файл urls .py от одноименных файлов в других приложениях в проекте . Пере- менная urlpatterns в этом модуле представляет собой список страниц, которые могут запрашиваться из приложения learning_logs . Схема URL представляет собой вызов функции path() с тремя аргументами . Первый аргумент содержит строку, которая помогает Django правильно марш- рутизировать текущий запрос. Django получает запрашиваемый URL и пытается отобразить его на представление. Для этого Django ищет среди всех определенных схем URL ту, которая соответствует текущему запросу. Базовый URL-адрес про- екта ( http://localhost:8000/ ) игнорируется, так что пустая строка совпадает с ба- зовым URL-адресом. Любой другой URL-адрес не будет соответствовать этому выражению, и Django вернет страницу с ошибкой, если запрашиваемый URL не соответствует ни одной из существующих схем URL. Второй аргумент path() определяет вызываемую функцию из views .py . Когда за- прашиваемый URL-адрес соответствует регулярному выражению, Django вызывает index() из views .py (мы напишем эту функцию представления в следующем разделе). Третий аргумент определяет имя index для этой схемы URL, чтобы на нее можно было ссылаться в других частях кода. Каждый раз, когда потребуется предоставить ссылку на домашнюю страницу, мы будем использовать это имя вместо URL. Написание представления Функция представления получает информацию из запроса, подготавливает данные, необходимые для построения страницы, и возвращает данные браузеру — часто с использованием шаблона, определяющего внешний вид страницы. Файл views .py в learning_logs был сгенерирован автоматически при выполнении коман ды python manage.py startapp . На данный момент его содержимое выглядит так: Начало работы над приложением 411 views.py from django.shortcuts import render # Создайте здесь свои представления. Сейчас файл только импортирует функцию render() , которая генерирует ответ на основании данных, полученных от представлений. Откройте файл представления и добавьте следующий код домашней страницы: from django.shortcuts import render def index(request): """Домашняя страница приложения Learning Log""" return render(request, 'learning_logs/index.html') Если URL запроса совпадает с только что определенной схемой, Django ищет в файле views .py функцию с именем index() , после чего передает этой функции представления объект request . В нашем случае никакая обработка данных для страницы не нужна, поэтому код функции сводится к вызову render() . Функция render() использует два аргумента — исходный объект запроса и шаблон, исполь- зуемый для построения страницы. Давайте напишем этот шаблон. Написание шаблона Шаблон определяет общий внешний вид страницы, а Django заполняет его соот- ветствующими данными при каждом запросе страницы. Шаблон может обращаться к любым данным, полученным от представления. Так как наше представление домашней страницы никаких данных не предоставляет, шаблон получается от- носительно простым. В каталоге learning_logs создайте новый каталог с именем templates . В каталоге templates создайте другой каталог с именем learning_logs . На первый взгляд такая структура кажется избыточной (каталог learning_logs в каталоге templates внутри каталога learning_logs ), но созданная таким образом структура будет однозначно интерпретироваться Django даже в контексте большого проекта, состоящего из множества отдельных приложений. Во внутреннем каталоге learning_logs создай- те новый файл с именем index .html (таким образом, полное имя файла имеет вид learning_log/learning_logs/templates/learning_logs/index .html ). Включите в него следу- ющий текст: index.html Learning Log Learning Log helps you keep track of your learning, for any topic you're learning about. Это очень простой файл. Если вы не знакомы с синтаксисом HTML, теги обозначают абзацы. Тег открывает абзац, а тег закрывает его. В нашей стра- 412 Глава 18 • Знакомство с Django нице два абзаца: первый содержит заголовок, а второй описывает, что пользователь может сделать с помощью приложения Learning Log. Теперь при запросе базового URL-адреса проекта http://localhost:8000/ вы увидите только что построенную страницу вместо страницы по умолчанию. Django берет запрошенный URL-адрес и видит, что он совпадает со схемой '' ; в этом случае Django вызывает функцию views.index() , что приводит к построению страницы с использованием шаблона, содержащегося в index .html . Полученная страница по- казана на рис. 18.3. Рис. 18.3. Домашняя страница Learning Log И хотя может показаться, что для одной страницы этот процесс слишком сложен, такое разделение URL-адресов, представлений и шаблонов работает хорошо. Оно позволяет сосредоточиться на отдельных аспектах проекта, а в более крупных проектах отдельные участники могут сосредоточиться на тех областях, в которых они наиболее сильны. Например, специалист по базам данных может заняться моделями, программист — кодом представления, а веб-дизайнер — шаблонами. ПРИМЕЧАНИЕ Вы можете получить следующее сообщение об ошибке: ModuleNotFoundError: No module named 'learning_logs.urls' В таком случае остановите сервер разработки нажатием клавиш Ctrl+C в терминальном окне, в котором была введена команда runserver . Затем снова введите команду python manage.py runserver . Каждый раз, когда вы сталкиваетесь с подобными ошибками, по- пробуйте остановить и перезапустить сервер . УПРАЖНЕНИЯ 18.5. План питания: представьте приложение для составления плана питания на неделю. Создайте новый каталог с именем meal_planner , а в этом каталоге — новый проект Django. Создайте новое приложение с именем meal_plans . Постройте простую домашнюю страницу для этого проекта. Построение других страниц 413 18.6. Домашняя страница Pizzeria: добавьте домашнюю страницу в проект Pizzeria , кото- рый вы начали строить в упражнении 18.4 (с. 408). Построение других страниц Теперь, когда вы начали представлять процесс построения страниц, можно пере- ходить к построению проекта Learning Log. Мы создадим две страницы для вывода данных: на одной будет выводиться список всех тем, а на другой — все записи по конкретной теме. Для каждой страницы мы создадим схему URL, напишем функ- цию представления и создадим шаблон. Но прежде чем переходить к работе, стоит создать базовый шаблон, от которого будут наследовать все шаблоны этого проекта. Наследование шаблонов При построении сайта некоторые элементы почти всегда повторяются на каждой странице. Вместо того чтобы встраивать эти элементы непосредственно в страницы, вы можете написать базовый шаблон с повторяющимися элементами; все страницы будут наследовать от этого шаблона. Такое решение позволит сосредоточиться на разработке уникальных аспектов каждой страницы и существенно упростит из- менение общего оформления проекта в целом. Родительский шаблон Начнем с создания шаблона base .html в одном каталоге с файлом index .html . Этот файл будет содержать элементы, общие для всех страниц; все остальные шаблоны наследуют от base .html . Пока единственным элементом, который должен повто- ряться на каждой странице, остается заголовок в верхней части страницы. Так как шаблон будет включаться в каждую страницу, преобразуем заголовок в ссылку на домашнюю страницу: base.html ❶ Learning Log ❷ {% block content %}{% endblock content %} Первая часть файла создает абзац с именем проекта, который также работает как ссылка на домашнюю страницу. Для построения ссылки использовался шаблонный тег, обозначенный фигурными скобками и знаками процента {% %} . Шаблонный тег представляет собой блок кода, который генерирует информацию для вывода на странице. В данном примере шаблонный тег {% url 'learning_logs:index' %} гене- рирует URL-адрес, соответствующий схеме URL, определенной в файле learning_ logs/urls .py с именем 'index' . В данном примере learning_logs — пространство имен, а index — схема URL с уникальным именем в этом пространстве имен. |