Проект - совокупность всего программного кода, составляющего разрабатываемый сайт. Физически он представляет собой папку, в которой находятся папки и файлы с исходным кодом.
папка Конфигурации (название условное) - пакет языка Python, содержащий модули, которые относятся к проекту целиком и задают его конфигурацию (в частности, ключевые настройки). Название этого пакета совпадает с названием проекта, и менять его не стоит — в противном случае придется вносить в код обширные правки.
Пакет в Python – это каталог, включающий в себя другие каталоги и модули, но при этом дополнительно содержащий файл __init__.py
. Пакеты используются для формирования пространства имен, что позволяет работать с модулями через указание уровня вложенности (через точку).
Приложение в терминологии Django — это отдельный фрагмент функциональности разрабатываемого сайта, более или менее независимый от других таких же фрагментов и входящий в состав проекта. Приложение может реализовывать работу всего сайта, его раздела или же какой-либо внутренней подсистемы сайта, используемой другими приложениями. Любое приложение представляется обычным пакетом Python.
Контроллер Django (он же view или представление) — это код, запускаемый при обращении по интернет-адресу определенного формата и в ответ выводящий на экран определенную веб-страницу.
Контроллер Django может представлять собой как функцию (контроллер-функция), так и класс (контроллер-класс). Первые более универсальны, но зачастую трудоемки в программировании, вторые позволяют выполнить типовые задачи, наподобие вывода списка каких-либо позиций, минимумом кода.
Путь — это часть интернет-адреса, находящаяся между адресом хоста и набором GET-параметров (например, интернет-адрес http://localhost:8000/bboard/34/edit/ содержит путь bboard/34/edit/).
Маршрутизатор - Важнейшей частью любого Web-фреймворка является механизм, отвечающий за маршрутизацию. В Django для этого используется свой небольшой eDSL, описывающий urlpatterns — набор образцов, с которыми сопоставляются пути из каждого входящего запроса.
Каждый образец состоит из описания статических и динамических частей пути в виде строки или регулярного выражения. Статические части пути в образце просто проверяются на равенство соответствующим участкам пути в запросе. Динамические же участки пути позволяют захватывать значения и передавать во view в качестве аргументов.
Как только выясняется, что путь или его начало совпали с образцом, происходит либо вызов view, либо передача оставшейся части пути во вложенный блок urlpatterns. В большинстве больших Django-проектов urlpatterns вложены друг в друга и представляют собой дерево.
Модель — это класс, описывающий определенную таблицу в базе данных, в частности набор имеющихся в ней полей. Отдельный экземпляр класса модели представляет отдельную запись таблицы, позволяет получать значения, хранящиеся в полях записи, и заносить в них новые значения. Модель никак не привязана к конкретному формату базы данных.
Объявим модель Bb, представляющую объявление, со следующими полями:
* title — заголовок объявления с названием продаваемого
товара (тип — строковый, длина — 50 символов).
Поле, обязательное к заполнению;
* content — сам текст объявления,
описание товара (тип — текст);
* price — цена (тип — вещественное число);
* published— дата публикации (тип— временная отметка,
значение по умолчанию — текущие дата и время,
индексированное).
Завершим работу отладочного веб-сервера. Откроем модуль models.py пакета приложения bboard и запишем в него следующий код
from django.db import models
class Bb(models.Model):
title = models.CharField(max_length=50)
content = models.TextField(null=True, blank=True)
price = models.FloatField(null=True, blank=True)
published = models.DateTimeField(auto_now_add=True,
db_index=True)
Рассмотрим использованные нами классы полей и их параметры:
Миграция — это программа, сгенерированная на основе заданной модели и создающая в базе данных все описанные этой моделью структуры: таблицу, поля, индексы, правила и связи.
Чтобы сгенерировать миграцию на основе модели Bb
, переключимся в командную строку, проверим, остановлен ли отладочный веб-сервер и находимся ли мы в папке проекта, и дадим команду:
python manage.py makemigrations bboard
Модуль с кодом нашей первой миграции будет иметь имя OOO1_initial.py.
from django.db inport migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [ ]
operations = [
migrations.CreateModel(
name='Bb’,
fields=[
...
],
) ,
]
fields=[
(’id’, models.AutoField(auto_created=True,
primary_key=True,
serialize=False,
verbose name=’ID’)),
(’title’,
models.CharField(max_length=50)),
(’content',
models.TextField(blank=True, null=True)),
('price',
models.FloatField(blank=True, null=True)),
('published',
models.DateTimeField(auto_now_add=True,
db_index=True)),],
Миграция при выполнении порождает команды на языке SQL, создающие в базе необходимые структуры. Посмотрим на SQL-код, создаваемый нашей миграцией, задав в командной строке команду:
python manage.py sqlmigrate bboard 0001
После команды sqlmigrate, выводящей SQL-код, мы поставили имя приложения и числовую часть имени модуля с миграцией:
BEGIN;
— Create model Bb
CREATE TABLE "bboard_bb" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" varchar(50) NOT NULL,
"content" text NULL,
"price" real NULL,
"published" datetime NOT NULL
);
CREATE INDEX "bboard_bb_published_58fde1b5"
ON "bboard_bb" ("published");
COMMIT;
Для выполнения первой миграции наберем в командной строке команду:
python manage.py migrate
Создадим первое объявление — первую запись модели Bb:
Для операций дальше нужно активировать консоль Django командой python manage.py shell
from bboard.models import Bb
bl = Bb(title='Дача',
content='Общество "Двухэтажники". Два этажа,
кирпич, свет, газ, канализация',
price=500000)
Чтобы сохранить запись в базу данных, достаточно вызвать у нее метод save()
о без параметров:
bl.save()
Проверим, сохранилось ли наше первое объявление, получив значение ключевого поля:
bl.pk
Мы можем обратиться к любому полю записи, воспользовавшись соответствующимему атрибутом класса модели:
bl.title
’Дача’
bl.content
'Общество "Двухэтажники". Два этажа,
кирпич, свет, газ, канализация'
bl.price
500000
bl.published
datetime.datetime(2019, 11, 21,
15, 17, 31, 695200, tzinfo=<UTC>)
bl.id
1
Создадим еще одно объявление:
b2 = Bb()
b2.title = 'Автомобиль'
b2.content = "Жигули"
b2.save ()
b2.рк
2
Давайте дополним ее:
b2.content = '"Жигули",
1980 года,
ржавая,
некрашеная,
сильно битая'
b2.save()
Добавим еще одно объявление:
Bb.objects.create(title='Дом',
content='Трехэтажный, кирпич',
price=50000000)
<Bb: Bb obj ect (3)>
Все классы моделей поддерживают атрибут класса objects. Он хранит диспетчер записей — объект, представляющий все имеющиеся в модели записи и являющийся экземпляром класса Manager.
Метод create()
диспетчера записей создает новую запись модели, принимая в качестве набора именованных параметров значения ее полей, сразу же сохраняет ее ивозвращает в качестве результата.
Выведем ключи и заголовки всех объявлений, имеющихся в модели Bb:
for b in Bb.objects.all():
print(b.pk, ': ', b.title)
Метод all
диспетчера записей возвращает набор записей— последовательность из всех записей модели, которую можно перебрать в цикле.
Отсортируем записи модели по заголовку:
for b in Bb.objects.order_by('title'):
print(b.pk, ': ', b.title)
Метод order_by()
диспетчера записей сортирует записи по значению поля, имя которого указано в параметре, и сразу же возвращает набор записей, получившийся в результате сортировки.
Извлечем объявления о продаже домов:
for b in Bb.objects.filter(title='Дом'):
print(b.pk, ': ', b.title)
Метод filter()
диспетчера записей фильтрует записи по заданным критериям.
Объявление о продаже автомобиля имеет ключ 2. Отыщем его:
b = Bb.objects.get(pk=2)
b.title
Метод get()
диспетчера записей имеет то же назначение, что и метод filter()
, и вызывается аналогичным образом. Однако он ищет не все подходящие записи, а лишь одну и возвращает ее в качестве результата.
Давайте удалим эту запись:
b.delete()
Метод delete () модели, как уже понятно, удаляет текущую запись и возвращает сведения о количестве удаленных записей, обычно малополезные.
Чтобы выйти из консоли, наберите команду exit()
Откроем модуль views.py пакета приложения bboard и исправим хранящийся в нем код:
from django.http import HttpResponse
from .models import Bb
def index(request):
s = 'Список объявлений\r\n\r\n\r\n'
for bb in Bb.objects.order_by('-published'):
s += bb.title + '\r\n' + bb.content + '\r\n\r\n'
return HttpResponse(s,
content_type='text/plain; charset=utf-8')
Рекомендации при создании базы данных:
Шаблон — это образец для генерирования веб-страницы, отправляемой клиенту в составе ответа. Генерированием страниц на основе шаблонов занимается подсистема Django, называемая шаблонизатором.
Шаблон Django — это файл с HTML-кодом страницы, содержащий особые команды шаблонизатора: директивы, теги и фильтры. Директивы указывают поместить в заданное место HTML-кода какое-либо значение, теги управляют генерированием содержимого, а фильтры выполняют какие-либо преобразования указанного значения перед выводом.
В файле settings.py
нахдим строку from pathlib import Path
и заменяем её на from pathlib import Path, os
Далее нам неоюнодимо добавить строку os.path.join(BASE_DIR, 'templates')
в параметр 'DIRS': []
. Это позволит задать папку для шаблонов по умолчанию.
TEMPLATES = [
{
...
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {...},
},
]
Создадим в папке пакета приложения bboard папку templates, а в ней — вложенную папку bboard. Сохраним в этой папке наш первый шаблон index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Главная :: Доска объявлений</title>
</head>
<body>
<h1>0бъявления</h1>
{% for bb in bbs %}
<div>
<h2>{{ bb.title }}</h2>
<p>{{ bb.content }}</p>
<p>{{ bb.published|date:"d.m.Y H:i:s"
}}</p>
</div>
{% endfor %}
</body>
</html>
Рассмотрим первый тег шаблонизатора:
{% for bb in bbs %}
...
{% endfor %}
Теперь познакомимся с директивой шаблонизатора:
{{ bb.title }}
И, наконец, фильтр date:
<р>{{ bb.published|date: "d.m.Y H:i:s" }}</p>
Откроем модуль views.py
пакета приложения bboard и внесем исправления в его код.
from django.http import HttpResponse
from django.template import loader
from .models import Bb
def index(request) :
template = loader.get_template('bboard/index.html')
bbs = Bb.objects.order_by('-published')
context = {'bbs': bbs}
return HttpResponse(template.render(context, request))
В коде контроллера index()
для рендеринга мы использовали низкоуровневые инструменты, несколько усложнив код. Но Django предоставляет средства более высокого уровня — функции-сокращения. Так, функция-сокращение render()
из модуля django.shortcuts выполняет и загрузку, и рендеринг шаблона.
Попробуем ее в деле, исправив код модуля views.py
:
from django.shortcuts import render
from .models import Bb
def index(request):
bbs = Bb.objects.order_by('-published')
return render(request, 'bboard/index.html',
{'bbs': bbs})