Мы будем использовать один базовый шаблон для всех приложений. Максимально раскрывая информацию о деятельности автора сайта и его публичных контактах.
Шаблоны в Django это не просто набор статических данных, но и возможность использовать динамику через специальный синтаксис.
Настройки
Добавляем следующие параметры в файл settings.py:
SITE_AUTHOR = 'Имя и фамилия'
SITE_TITLE = SITE_AUTHOR
SITE_SUBTITLE = 'Ликбез по охране труда'
Заданные настройки найдут применение не только в базовом шаблоне, но и, например, в выводе ленты последних публикаций.
Контекстный процессор
Для передачи параметров в шаблон необходимо создать файл в каталоге core c названием context_processors.py со следующим содержимым:
from django.conf import settings
def site(request):
return {
'SITE_AUTHOR': settings.SITE_AUTHOR,
'SITE_TITLE': settings.SITE_TITLE,
'SITE_SUBTITLE': settings.SITE_SUBTITLE,
}
Мы создаем функцию, которая принимает обязательный для контекстных процессоров аргумент request.
Затем собираем настройки в словарь, где ключ словаря — это название которое будет использоваться в шаблоне, а значением выступает заданный параметр.
В файл настроек settings.py добавляем созданный процессор в список контекстных процессоров шаблонов:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'core.context_processors.site',
],
},
},
]
Шаблон
Переходим в каталог templates проекта и создаем файл base.html со следующей начинкой:
{% load static %}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="{{ SITE_AUTHOR }}">
<title>{% block title %}{% endblock %} | {{ SITE_TITLE }}</title>
<!-- Bootstrap -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!-- Style -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700%7CUbuntu:700&subset=cyrillic" rel="stylesheet">
<link rel="stylesheet" href="{% static 'style.css' %}">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<header>
<div class="container">
<div class="about">
<div class="row">
<div class="col-sm-8">
<h2 class="title"><a href="/">{{ SITE_TITLE }}</a></h2>
<h3 class="subtitle">{{ SITE_SUBTITLE }}</h3>
</div>
<div class="col-sm-4">
<address class="contacts">
<div class="mail">
<span class="sr-only">Адрес электронной почты</span>
<i class="fa fa-envelope-o fa-fw" aria-hidden="true"></i>
Почта
</div>
<div class="location">
<span class="sr-only">Местоположение</span>
<i class="fa fa-globe fa-fw" aria-hidden="true"></i>
Местоположение
</div>
</address>
</div>
</div>
<div class="description">
<p>
В течение десяти лет работы на крупных производственных предприятиях заполучил опыт создания служб с нуля,
по направлениям: охрана труда, пожарная, промышленная и экологическая безопасность.
</p>
<p>
Проведу для Вас полный аудит или разработаю комплекты документов по всем вышеперечисленным направлениям.
</p>
</div>
</div>
</div>
</header>
<main>
<div class="container">
{% block main %}{% endblock %}
</div>
</main>
</body>
</html>
В самом начале шаблона необходимо загрузить зависимости. Мы импортируем файл с шаблонными тегами стандартного приложения staticfiles.
Тег static генерирует URL по заданному относительному пути каталога статики. Это очень удобно, например, в настройках проекта можно сменить URL и перенести статические файлы на отдельный сервер без каких-либо изменений маршрутов в шаблонах.
Настройки, которые мы ранее передали через контекстный процессор принято обрамлять в шаблоне пробелом и двойными фигурными скобками с обеих сторон.
И самое главное здесь это блоки title и main, которые мы будем переопределять в дочерних шаблонах.
Например, в шаблоне логина пользователя, в заголовке мы укажем "Вход", а в основном блоке — HTML форму для проведения процедуры авторизации.
Все остальное это вполне стандартный код HTML с классами от фреймворка Bootstrap.
Пожалуй, здесь можно выделить "колоночную верстку" которая будет приятно смотреться и мониторах, и на маленьких устройствах одновременно.
И класс sr-only. Скрывает содержимое тега, но призван помочь пользователям, которые используют программы для чтения с экрана, произнести эту метку вслух.
Стили
В базовом шаблоне мы уже подключили таблицу стилей, теперь нам необходимо ее создать в директории static проекта — файл style.css следующего вида:
body {
font-family: 'Open Sans', sans-serif;
font-size: 15px;
line-height: 160%;
color: black;
}
h1, h2, h3, h4, h5, h6 {
font-family: 'Ubuntu', sans-serif;
text-transform: uppercase;
font-weight: bold;
}
.container {
max-width: 750px;
}
header .about .title {
font-size: 28px;
margin: 0;
}
header .about .title a {
color: black;
}
header .about .subtitle {
margin-top: 0;
font-family: 'Open Sans', sans-serif;
font-size: 18px;
font-weight: normal;
}
header .about .contacts {
text-align: right;
font-size: 18px;
margin-top: 5px;
line-height: 130%;
}
header .about .contacts .location {
margin-right: 3px;
}
header .about .description {
margin-top: 15px;
}
main {
margin-top: 10px;
margin-bottom: 40px;
}
main h1 {
font-size: 22px;
margin-bottom: 30px;
}
main a {
font-weight: bold;
}
main form .errorlist {
list-style-type: none;
padding-left: 5px;
}
main form button {
margin-top: 10px;
}
main blockquote {
font-size: 14px;
border-color: #e6e6e6;
background-color: #f7f7f7;
}
main .django-ckeditor-widget {
width: 100%;
}
main .accounts-login .links {
margin-top: 25px;
}
main .questions-index .question .title {
font-size: 18px;
margin-top: 3px;
}
main .questions-index .pagination {
margin-top: 25px;
margin-bottom: 5px;
}
main .questions-index .your-question h2 {
font-size: 20px;
margin-top: 40px;
margin-bottom: 20px;
}
main .questions-question .title {
margin-bottom: -30px;
}
main .questions-question .article {
margin-top: 50px;
}
main .questions-question .answer {
color: darkgreen;
}
main .questions-question .article .expert {
margin-right: 5px;
}
main .questions-question .article .author {
font-weight: bold;
margin-bottom: 5px;
}
main .questions-question .article .created {
color: #666666;
margin-right: 5px;
}
main .questions-question .article .text {
margin-top: 20px;
}
main .questions-question .your-answer h2 {
font-size: 20px;
margin-top: 50px;
margin-bottom: 20px;
}
main .questions-question .your-answer form {
margin-top: -25px;
}
main .questions-question .your-answer label {
visibility: hidden;
}
main .articles-index .article .title {
font-size: 18px;
margin-top: 3px;
}
main .articles-article .title {
margin-bottom: 5px;
}
main .articles-article .published {
color: #666666;
margin-right: 5px;
}
main .articles-article .text {
margin-top: 20px;
}
main .articles-article .text h2 {
font-size: 20px;
margin-top: 25px;
margin-bottom: 15px;
}
main .articles-article .text h3 {
font-size: 18px;
margin-top: 25px;
margin-bottom: 15px;
}
main .articles-article .text ul {
margin-bottom: 20px;
}
main .articles-article .text p {
margin-bottom: 15px;
}
/* Маленькие устройства (телефоны) (<768px) */
@media (max-width: 767px) {
header .about .contacts {
margin-top: 25px;
text-align: left;
}
header .about .description {
margin-top: 10px;
}
main {
margin-bottom: 20px;
}
}