Часть восьмая. Настройка базы данных
Базовая работа с базами данных
Цель: Создать и настроить базы данных
Задачи:
    Создание файла сборки базы данных
    Создание базы данных
    Миграция баз данных
    Отображение баз данных в динамическом режиме

Создание шаблона сборки базы данных

Статьи, которые выведены на сайте созданы при помощи ручного кодирования. Нам необходимо сделать так, чтобы статья формировалась сама из базы данных, которую сейчас мы создадим и настроим.
Откроем файл models.py. Мы делаем базу данных только для приложения blog, а это значит, что и работать будем из директории приложения.
Сейчас этот файл выглядит так:
1
from django.db import models
2
3
# Create your models here.
Copied!
Напишем небольшой код:
1
from django.db import models
2
from django.utils import timezone
3
from django.contrib.auth.models import User
4
5
6
class New(models.Model):
7
title = models.CharField(max_length=100)
8
text = models.TextField()
9
data = models.DateTimeField(default=timezone.now)
10
author = models.ForeignKey(User, on_delete=models.CASCADE)
Copied!
Построчно разберёмся в коде. Первая строка – импорт модели базы данных мы не меняем. Вторая строка и вторая библиотека, которая нам понадобится – timezon. Мы будем делать вывод текущих даты и времени после написания статьи. Последняя библиотека, которая нам нужна – User. Она нужна для того, чтобы из таблички пользователей взять авторов и поместить её в новую таблицу. С библиотеками закончили. Теперь – сам класс New.
Таблица, которую мы можем увидеть в панели администратора (см. предыдущий урок) – это класс со значениями. Нам нужно сделать таблицу с четырьмя столбцами – заголовок статьи (title), текст статьи (text), дата публикации (data) и автор статьи (author). Автором может быть только тот пользователь, который есть в таблице Users.
Каждый столбец принимает отдельный тип данных. В столбце title мы будем принимать текст, максимальная длина которого – 100 символов (models.CharField(max_length=100)). То есть, мы обращаемся к библиотеке models, из неё берём объект CharField (ввод строки) и выставляем это поле на максимальную длину на 100 символов (max_length=100). В столбце text мы берём текстовое поле без ограничений в размере. Текст – html-текст. В data мы поместим дату публикации. Для этого мы вводим поле даты (DateTimeField) и выставляем значением по умолчанию текущую дату и время в часовой зоне пользователя (Django способен определять зону по IP-адресу и синхронизировать время с зоной). Последний столбец – автор публикации (author). Так как, пользователи уже созданы и находятся в таблице Users, нам не требуется заново их вводить, а нужно лишь обратиться за ключом (в каждой таблице элемент называется ключом) и вывести его. Для этого обратимся к ForeignKey. Запросим таблицу с данными – User. Если же пользователь с сайта будет удалён, мы можем вывести вместо его имени что-то (например, фразу "User deleted") или же мы можем удалить эту запись совсем. Я выбрал удаление записи, так как оно сложнее в написании и будет этот метод выглядеть так: on_delete=models.CASCADE. Если же на нужно оставить запись и вывести фразу, то делается это так: on_delete='User deleted'. Как вы видите, ничего сложного.
Теперь выполним миграцию. Введём знакомую команду:
1
python manage.py makemigrations
Copied!
Диалог сообщает нам о создании новой модели New:
1
C:\Users\Valery\PycharmProjects\MySite>python manage.py makemigrations
2
Migrations for 'blog':
3
blog\migrations\0001_initial.py
4
- Create model New
Copied!
Откроем в нашем приложении папку миграций: C:\Users\Valery\PycharmProjects\MySite\blog\migrations
В папке мы можем увидеть созданный нами файл – 0001_initial.py. Заглянем внутрь файла:
1
# Generated by Django 3.0.3 on 2020-05-20 10:35
2
3
from django.conf import settings
4
from django.db import migrations, models
5
import django.db.models.deletion
6
import django.utils.timezone
7
8
9
class Migration(migrations.Migration):
10
11
initial = True
12
13
dependencies = [
14
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
15
]
16
17
operations = [
18
migrations.CreateModel(
19
name='New',
20
fields=[
21
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22
('title', models.CharField(max_length=100)),
23
('text', models.TextField()),
24
('data', models.DateTimeField(default=django.utils.timezone.now)),
25
('author', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
26
],
27
),
28
]
Copied!
Файл создан Django автоматически. В классе миграции обратите внимание на список operations. Мы задали имя новой таблице и в неё ввели все данные (title, text, data, author). Плюс к этому, перед всеми элементами списка был автоматически создан элемент id. На каждом сайте все элементы должны иметь свой уникальный номер в вёрстке (id). Этот элемент создаётся Django автоматически.

Создание базы данных

Нужно понимать, что файл с расширением .py не является базой данных. Базы данных хранятся в sql-файлах. Исправим же это.
Запустим ещё пару команд:
1
python manage.py sqlmigrate blog 0001
2
python manage.py migrate
Copied!
Первой командой мы запустили процесс сборки sql-файла из файла 0001_initial.py. Второй командой выполнили полную миграцию баз данных.
Диалоги:
1
C:\Users\Valery\PycharmProjects\MySite>python manage.py sqlmigrate blog 0001
2
BEGIN;
3
--
4
-- Create model New
5
--
6
CREATE TABLE "blog_new" ("id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
7
"title" varchar(100) NOT NULL, "text" text NOT NULL, "data" datetime NOT NULL,
8
"author_id" integer NOT NULL REFERENCES "auth_user" ("id") DEFERRABLE INITIALLY
9
DEFERRED);
10
CREATE INDEX "blog_new_author_id_eb387d4f" ON "blog_new" ("author_id");
11
COMMIT;
12
13
C:\Users\Valery\PycharmProjects\MySite>python manage.py migrate
14
Operations to perform:
15
Apply all migrations: admin, auth, blog, contenttypes, sessions
16
Running migrations:
17
Applying blog.0001_initial... OK
Copied!
Запустим сервер и проверим результат:
Как мы видим, в панели администратора ничего нет. Исправим это перейдя в файл admin.py
В нём нет ничего нужного нам для вывода:
1
from django.contrib import admin
2
3
# Register your models here.
Copied!
Исправим это:
1
from django.contrib import admin
2
from .models import New
3
4
admin.site.register(New)
Copied!
Из файла models.py мы запросили класс New и зарегистрировали его на сайте одной командой.
Проверка:
Всё работает. Обратите внимание, к каждому классу добавляется автоматически буква "s" в конце.

Добавление записей

Создадим несколько статей. Нажмём на News и в верхнем правом углу нажмём кнопку «ADD NEW»
Введём любые данные в поля и сохраним результат. Я ввёл 3 примера статей:

Динамический вывод базы данных

Теперь мы можем удалять/добавлять/изменять статьи в графическом режиме из панели администратора. Но на сайте мы видим следующую картину:
Исправим это. Зайдём в файл, который передаёт все данные на html-страницы (views.py). Мы увидим следующую картину статических данных (news):
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', {'title': 'Страничка про МИИГАиК'})
Copied!
Исправим все данные в этом файле:
1
from django.shortcuts import render
2
from .models import New
3
4
5
def home(request):
6
data = {
7
'news': New.objects.all(),
8
'title': 'Главная страница'
9
}
10
return render(request, 'blog/home.html', data)
11
12
13
def contacts(request):
14
return render(request, 'blog/contacts.html', {'title': 'Страничка про МИИГАиК'})
Copied!
Единственные 2 пункта, которые нужно поменять:
    Импорт New
    Передача всех объектов в файле New ('news': New.objects.all(),)
Проверка:
Почти победа, но исчезла дата публикации. Исправим. В файле home.py мы назвали переменную передачу даты – date, а в базе данных – data. Изменим 1 букву и получим:
1
{% extends 'blog/main.html' %}
2
{% block main_section %}
3
{% for post in news %}
4
<div class="alert alert-light">
5
<h1>{{ post.title }}</h1>
6
<p>{{ post.text }}</p>
7
<span class="text-muted">Публикация: {{ post.data }}</span>
8
{% if post.author == 'Валерий' %}
9
<p><b>Автор:</b> <mark>Админ</mark></p>
10
{% else %}
11
<p><b>Автор:</b> <mark>{{ post.author }}</mark></p>
12
{% endif %}
13
</div>
14
{% endfor %}
15
{% endblock main_section %}
Copied!
Единственный момент, который сейчас не удобен и выглядит странно – дата. Во-первых, оно выглядит не красиво и во-вторых, на английском языке.
Подредактируем файл home.html, а конкретно строку:
1
<span class="text-muted">Публикация: {{ post.data }}</span>
Copied!
Исправим это на:
1
<span class="text-muted"><b>Дата:</b> {{ post.data|date:'j F Y, время: H:i:s' }}</span>
Copied!
Все ключи я брал из документации Django – https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#date
Результат:
Последний штрих – изменим американский «May» на русский «Май». Переходим в файл настройки всего проекта (setting.py) и найдём строку:
1
LANGUAGE_CODE = 'en-us'
Copied!
Заменим её на:
1
LANGUAGE_CODE = 'ru-RU'
Copied!
Результат:
Мало того, что мы изменили язык на сайте, мы ещё и перевели его панель администратора:
Last modified 10mo ago