Часть четвёртая. Шаблон сайта
Делаем простые шаблоны
Цель: Создание полноценного сайта с простых шаблонов
Задачи:
    Создание простых страниц на HTML
    Изменение ссылок внутри проекта
    Введение динамических и статических элементов страницы

Создаём html-страницы

В этой части курса мы научимся выводить полноценные html-страницы. Так как, мы хотим создать шаблон страниц, а не просто одну страницу, мы должны прибегнуть к полноценной вёрстке на Python. Для этого, в папке нашего приложения blog, нужно создать папку templates. Название папки зарезервировано плагином Django, так как Django каждый раз собирает наши файлы и с нуля отрисовывает страницу. При сборке сайта, джанго обращается к папкам и файлам с конкретными названиями.
Папка "blog"
Теперь, в папке templates, нам нужно создать ещё одну папку, которая точно также называется, как и приложение, то есть в нашем случае – blog.
Почему именно так? Дело в том, что Django собирает все папки в единую папку templates. Сейчас у нас одно приложение – blog, но если бы у нас было бы ещё несколько приложений, то в папке templates был бы хаос из файлов. Несмотря на то, что у нас одно приложение, мы будем писать сайт с правилами хорошего тона в программировании.
Теперь в папке blog, создадим файлы home.html и contacts.html
Как мы видим, файлы у нас не пусты.
1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<title>Title</title>
6
</head>
7
<body>
8
9
</body>
10
</html>
Copied!
Удалим всё лишнее.
Настроим PyCharm. Нам потребуется плагин для работы с html-файлами. Плагин называется – Emmet.
Переходим в IDE по следующей ветке: File -> Settings
В панели поиска напишем название нашего плагина
Обычно, он установлен по умолчанию и находится во вкладке Editor. Если его у вас нет, нажмите кнопку Install в появляющемся после запроса окне.
Как мы видим, плагин будет реагировать на кнопку “Tab”. Это нам и нужно. Нажимаем ОК и возвращаемся к файлам html.
Введите ! и нажмите Tab.
Весь текст набрался самостоятельно
Не меняем ничего, кроме двух пунктов.
    1.
    Удалим в поле <title> слово “Documents”
    2.
    В теле введём заголовок <h2>
Результат (contacts.html):
1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
6
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7
<title></title>
8
</head>
9
<body>
10
<h2>Контакты работают иначе</h2>
11
</body>
12
</html>
Copied!
Теперь, чтобы шаблоны были доступны, необходимо в главном файле настройки проекта – settings.py в установленных приложениях (INSTALLED_APPS) ввести наше приложение – blog.
Сделаем тоже самое для главной страницы.
Результат (home.html):
1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
6
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7
<title></title>
8
</head>
9
<body>
10
<h2>Ура! Главная страница поменялась</h2>
11
</body>
12
</html>
Copied!
Переходим к файлу настроек и вписываем туда строку:
blog.apps.BlogConfig
Таким образом, мы вводим приложение blog, сведения о котором хранятся в файле apps и обращаемся к функции BlogConfig.
Результат:
1
INSTALLED_APPS = [
2
'blog.apps.BlogConfig',
3
'django.contrib.admin',
4
'django.contrib.auth',
5
'django.contrib.contenttypes',
6
'django.contrib.sessions',
7
'django.contrib.messages',
8
'django.contrib.staticfiles',
9
]
Copied!
Взглянем на файл apps.py в проекте сайта.
1
from django.apps import AppConfig
2
3
4
class BlogConfig(AppConfig):
5
name = 'blog'
Copied!
Остался последний шаг – настроить vievs.py. Сейчас там прописаны функции – HttpResponse, то есть ответы через http. Это неправильно. Сайт будет работать на html вёрстке и нам нужно не выдавать http ответы, а обращаться к html шаблонам. Исправляем:
1
from django.shortcuts import render
2
from django.http import HttpResponse
3
4
5
def home(request):
6
return render(request, 'blog/home.html')
7
8
9
def contacts(request):
10
return render(request, 'blog/contacts.html')
Copied!
Обратите внимание на сигналы PyCharm:
Строка с импортом библиотеки HttpResponse стала серой. Это знак того, что мы не использовали в фале программы эту библиотеку. Её можно удалить.
Помимо прочего, появилось зелёные ярлычки слева. Это знак, что мы обращаемся к нашему html-файлу. Если навести на него курсор, отобразиться имя файла, а если кликнуть по нему, мы перейдём в этот файл.
Запускаем сервер и проверяем как всё работает:
Всё работает как надо!

Создаём html-страницы с динамическими данными

Теперь научимся передавать динамические данные. Это – заготовка под базы данных, которыми мы потом будем пользоваться.
Перейдём в файл views.py.
Написав немного кода, я изменил файл так:
1
from django.shortcuts import render
2
3
news = [
4
{
5
'title': 'Первая запись',
6
'text': 'Много-много текста',
7
'date': '10 Мая 2020',
8
'author': 'Валерий'
9
},
10
{
11
'title': 'Вторая запись',
12
'text': 'Снова много-много текста',
13
'date': '19 Мая 2020',
14
'author': 'Егор'
15
}
16
]
17
18
19
def home(request):
20
data = {
21
'news': news,
22
'title': 'Главная страница'
23
}
24
return render(request, 'blog/home.html', data)
25
26
27
def contacts(request):
28
return render(request, 'blog/contacts.html')
Copied!
Построчно разберём что к чему. Создан список news, состоящий из 2 записей. Каждая запись – это словарь. В каждом словаре по 4 элемента. В функции отрисовки главной страницы, я добавил переменную data, которая создаёт словарь news и вызывает в него созданный список новостей. Плюс к этому, в data мы вызывает ещё один объект – заголовок страницы (title). В самом же рендере, мы добавили переменную в конце и вызываем её.
Теперь перейдём в html-файл нашей главной страницы (home.html)
Снова написав немного кода, получаем следующее:
1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
6
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7
<title>{{ title }}</title>
8
</head>
9
<body>
10
{% for post in news %}
11
<h1>{{ post.title }}</h1>
12
<p>{{ post.text }}</p>
13
{% if post.author == 'Валерий' %}
14
<p>Автор: Админ</p>
15
{% else %}
16
<p>Автор: {{ post.author }}</p>
17
{% endif %}
18
<p>Дата: {{ post.date }}</p>
19
{% endfor %}
20
</body>
21
</html>
Copied!
В поле \ мы вызываем нужную нам строку – «Главная страница». В теле мы используем 2 конструкции:
    1.
    for
    2.
    if
Так как, мы пишем вёрстку на Python в html-файле, конструкции используются при помощи такой конфигурации: {% %}
Если бы мы писали тот же код, но на чистом питоне, выглядел бы он так:
1
for post in news:
2
print('post.title')
3
print('post.text')
4
if post.author == 'Валерий':
5
print('Автор: Админ')
6
else:
7
print('Автор: ', post.author)
8
print('Дата: ', post.data)
Copied!
Посмотрите основные отличия:
    Отсутствие двоеточий после for и if, но наличие конструкции endfor и endif
    Добавлена разметка html, то есть <p>, <h2> и т.п.
    Отсутствие кавычек и слова "print"
Запустим сервер и посмотрим на результат:
Подредактируем ещё немного файл views.py. Допустим, нам нужно вывести только заголовок (title), а остаток кода не менять и не выводить все новости (data). В таком случае, сделаем следующую конструкцию:
1
def contacts(request):
2
return render(request, 'blog/contacts.html', {'title': 'Страничка про МИИГАиК'})
Copied!
А в файл contacts.html выглядит теперь так:
1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
6
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7
<title>{{ title }}</title>
8
</head>
9
<body>
10
<h2>Контакты работают иначе</h2>
11
</body>
12
</html>
Copied!
Проверяем:
Теперь давайте сравним 2 файла home.html и contacts.html. Что в них отличается?
Единственный блок, который у них отличается – тело, а «шапка» (верхняя часть сайта) и «подвал» (нижняя часть сайта) остаются одинаковыми. Конечно, нам не будет интересно переписывать один и тот же код на каждой странице. Давайте исправим это неудобство.
Создадим рядом с файлами home.html и contacts.html файл main.html и пишем в него следующий код:
1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
6
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7
<title>{{ title }}</title>
8
</head>
9
<body>
10
{% block main_section %}
11
{% endblock %}
12
</body>
13
</html>
Copied!
То есть, мы можем скопировать весь код с любого из html-файла и в теле сайта записать блочную конструкцию:
1
{% block main_section %}
2
{% endblock %}
Copied!
Перейдём в файл contacts.html и перепишем его таким образом:
1
{% extends 'blog/main.html' %}
2
{% block main_section %}
3
<h2>Контакты работают иначе</h2>
4
{% endblock main_section %}
Copied!
То есть, мы обращаемся к файлу blog/main.html и из него берём всё, что было до блока, пишем блок (тело страницы) и забираем всё, что нужно после. Повторяем операцию с файлом home.html.
1
{% extends 'blog/main.html' %}
2
{% block main_section %}
3
{% for post in news %}
4
<h1>{{ post.title }}</h1>
5
<p>{{ post.text }}</p>
6
{% if post.author == 'Валерий' %}
7
<p>Автор: Админ</p>
8
{% else %}
9
<p>Автор: {{ post.author }}</p>
10
{% endif %}
11
<p>Дата: {{ post.date }}</p>
12
{% endfor %}
13
{% endblock main_section %}
Copied!
Проверяем и видим тоже самое. Давайте теперь напишем какую-нибудь глобальную фразу в main.html. Например, так:
1
<!doctype html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
6
<meta http-equiv="X-UA-Compatible" content="ie=edge">
7
<title>{{ title }}</title>
8
</head>
9
<body>
10
<h1>МИИГАиК - лучший ВУЗ!</h1>
11
{% block main_section %}
12
{% endblock %}
13
</body>
14
</html>
Copied!
Проверим что получилось:
Теперь эта фраза нас преследует везде и на каждой странице. Сейчас это изменение можно убрать, так как нам ещё предстоит много работы со станицами.
Last modified 10mo ago