django

Чтобы я хотел знать когда начинал изучать Django? — очень общий взгляд

  • понедельник, 6 июля 2020 г. в 00:25:26
https://habr.com/ru/post/508100/
  • Django
  • Python


Здесь на хабре много различных инструкций по использованию Django. Эти инструкции часто включают много кода и представляют последовательность шагов, которые нужно сделать, чтобы создать проект.
Когда я начинал изучать Django и Wagtail по таким инструкциям, меня часто смущало, что пара команд создает кучу непонятных файлов (особенно на самом старте). Последующее описание этих файлов в инструкциях содержало слишком много деталей, которые трудно было усвоить за раз.
В этом посте я бы хотел посмотреть на Django с очень «философского вида» — минимум кода, максимум общих фактов. Думаю, что такой взгляд поможет тем, кто хочет начать изучать Django но теряется на старте.
image

Хочу также сказать, что не являюсь профессионалом по части веб-программирования — я в этой области скорее любитель, которого интересуют исключительно личные проекты — один из них сайт по расшифровке данных ДНК тестов https://ru.bezoder.com — написан на Wagtail.
Сначала давайте вспомним, что сайт в интернете это просто программа, которая, возможно, работает почти на таком же компьютере, что находится перед вами.
Ваш компьютер (телефон и т.п.) посылает какой-то запрос к чужому компьютеру в интернет, тот его обрабатывает и отвечает. При обработке чужой компьютер, возможно, делает запрос или производит запись в базу данных. Теперь представим, что необходимо запрограммировать компьютер в интернете, чтобы он правильно обрабатывал каждый запрос.
Это можно сделать вообще на каком угодно языке программирования — вы получаете запрос и на его основе что-то выполняете. Но представьте сколько может быть вариантов как запрограммировать этот компьютер — их может быть бесконечно много! Например, можно написать функцию что-то вроде:
Если запрос == google.ru:
ответ "Привет"
Если запрос == google.de:
ответ "Hallo"
...

Думаю, понятно, что это был бы ужасный вариант программирования.
Нам нужно сделать все так, чтобы код был читаемым, безопасным, легко дополняемым, использовал какие-то возможности языка, на котором написан…
С таким набором задач нужно придумать какую-то концепцию.

Концепция Django


Django предлагает все разделить на "слои". Слои отвечают за разные составляющие вашей программы. Между слоями есть связь, но она не затрудняет разработку каждого слоя изолированно (без большого внимания к другим слоям) — в Django это называется loose coupling. Вот несколько важных слоев Django:
  • Модели (Models) это слой ваших данных и то как вы их храните их в базе данных
  • Виды (views) этот слой собирает все данные которые необходимо для создания веб страниц или обработки данных, отправленных через формы
  • Шаблоны (Templates) этот слой получает данные из видов и отображает их на вебстранице (в этом слое вы работаете уже с html)
  • Ссылки (url) этот слой организует работу ссылок на вашем сайте на какую ссылку нужно создавать какой вид и какой шаблон
  • Формы (Forms) этот слой помогает создавать и обрабатывать веб формы для данных от пользователей
  • ...

Django дает инструменты для создания таких слоев и функционирование программы заключается в обмене данными между слоями.
Тут я немного подробнее остановлюсь на слоях Модели, Виды и Шаблоны.

Слой модели


Первый и, наверно, самый важный слой это модели(models) — отвечает за базу данных. База данных это много всяких таблиц — например, может быть таблица «пользователи» такого вида:
ID
name
surname
karma
1
Михаил
Трунов
2

Как видите, в базе каждая строка это запись, относящаяся к пользователю сайта. В строке есть данные различного типа — в нашем случае числа и текст.
Распространенным языком баз данных является SQL — определенными командами вы можете создавать новые таблицы в базе или вносить и получать данные в и из существующих таблиц.
У SQL есть уязвимости — подробнее. Вкратце — если определенным образом расставить кавычки и точки с запятой в данных, которые отправляются в SQL команду, часть этих данных может быть интерпретирована как составляющая SQL команды.
Django берет всю головную боль, связанную с проблемами SQL на себя — вам даже не надо знать SQL, чтобы пользоваться Django, от вас нужен только python — Django сам сформирует SQL команды для создания таблиц, поиска и записи данных в таблицы и все это будет безопасно.
Идея Django в том, что классы на python повторяют структуру таблиц вашей базы данных.
То есть, для таблицы выше я могу создать класс в python что-то вроде:
class User:
    def __init__(id, name, surname, karma)
        self.id = id
        self.name = name
        ...

но как связать такой класс с базой данных? Вот тут начинается магия Django:
# мы просто импортируем модуль models из Django
from django.db import models
# создаем класс, который наследует models.Model
class CustomUser(models.Model):
    # создаем поля для базы данных в классе
    name = models.CharField(max_length = 20)
    ...
    karma = models.FloatField(...)        
    ...
# Еще одна таблица в базе данных - статья
class Article(models.Model):
    # создаем название и содержание статьи
    title = models.CharField(...)
    content = models.TextField(...)        
    ...

Вы просто используете django.db.models.Model чтобы создать класс, далее каждое поле в вашем классе это также поле, взятое из django.db.models. В моем случае поле name это текстовое поле CharField, поле karma это число float. Список всех полей (Field types) есть в официальной документации.
У каждого поля есть опции (Field options) — в коде выше опция это max_length = 20. Опции зависят от полей, которые вы создаете в базе — например, max_length = 20 это максимальная длина в символах поля name в базе. В документации по ссылке выше также описаны опции для всех полей.
На основе этого кода Django сам создаст таблицу в базе данных и то, что я назвал полями в классе будут столбцами в этой таблице. Django дает вам также удобные команды в python как получать или записывать значения в базу данных. Все делается с помощью методов models.Model а также абстракции «Manager», отвечающей в Django за коммуникацию с базой данных (в данном посте я эти абстракции детально не рассматриваю). Например, CustomUser.objects.filter(name=«Михаил») вернет всех пользователей с именем «Михаил».
Такая связь между строками в базе данных и объектами (экземплярами, инстансами) в Python называется Object-relational mapping — в нашем случае Django-ORM.
А наши модели повторяют структуру базы данных и при этом являются классами в Python. Это значит, что к моделям (классы в Python) можно добавить методы. Например, продолжая логику сайта хабр, я могу добавить метод для изменения кармы:
from django.db import models

class CustomUser(models.Model):
    ...
    # пример метода в модели Django
    def change_karma(self, other):         
         ....
         if ...:
              self.karma = self.karma +1
              ...
         else:
         ...

Тут other — это другой пользователь. Как вы знаете здесь определенная логика добавления кармы. Всю эту логику я могу, например, создать в указанном методе.
В Django вы думаете какие таблицы хотите создать в своей базе и потом просто создаете классы python по примеру выше.

Слой виды


Следующим важным, на мой взгляд, слоем является слой видов (views). Ваши модели это некоторые абстракции, с которыми вам удобно работать или они интуитивно понятны. Но, когда вы хотите что-то показать пользователям, то, возможно, вас будут интересовать иные абстракции.
Например, вы создали три модели в Django: CustomUser, Article и Advertisement с разными полями. Модель Article это статья сайта, Advertisement — это реклама, которую вы показываете на сайте, CustomUser — зарегистрированный пользователь сайта.
Когда вы захотите создать вебстраницу со статьей, то вам понадобятся данные сразу из нескольких ваших моделей — разумеется вы хотите показать все поля в самой статье (название, содержание и т.д.), вы, скорее всего, также хотите показать какую-то рекламу рядом с этой статьей. Причем реклама зависит не от содержания статьи а от поведения пользователя CustomUser. При таком подходе будет нужна какая-то логика — как собирать данные. Так, слой view в данном случае и будет подходящим местом для этой логики. Тут можно собрать все данные, которые будут относиться к тому, что вы хотите показать.
Есть два типа видов view в Django — функциональный и классовый.
Функциональный вид это просто Python функция с аргументом request — это запрос к вашему сайту. В нем содержится информация о пользователе, типе запроса и многом другом. На основе этой информации вы формируете ответ и возвращаете его в своей функции.
Еще один тип view — классовый. Он позволяет создавать виды не на основе функций, а виды как экземпляры классов. Тут Django предоставляет также кучу всяких облегчающих жизнь классов и функций. Предположим, вы хотите создать вид на основе статьи Article:
# импорт полезного класса
from django.views.generic import DetailView
# импорт созданной в другом файле модели Article
from .models import Article
# создание классового вида 
class ArticleDetailView(DetailView):
    # модель на основе которой мы хотим создать вид
    model = Article
    # имя, которое будет использовано в html шаблоне (это другой слой - рассмотрим далее)
    context_object_name = 'article'
    # имя html шаблона, на основе которого будет создана веб страница
    template_name = 'article/article_detail.html'

Классовый вид на основе DetailView автоматически соберет всю информацию модели Article и затем отправит ее в следующий слой Django:

Слой шаблоны


В коде выше template_name это переменная для названия html шаблона, который будет использован для формирования веб страницы, которая и будет показана пользователю. Вот пример кода из такого шаблона:
  <h1>{{ article.title }}</h1> 
  <div>{{ article.content }}</div>       

{{ article.title }} и {{ article.content }} это название статьи и ее содержание, заключенные в html теги. title и content повторяют название полей модели Article, которую вы создали в слое Модели. Слово article мы указали в context_object_name в виде. В результате обработки Django вставит соответствующие поля из Article в шаблон.

Резюме


Это общий взгляд на некоторые Django слои. Описанная концепция позволяет разделить отдельные блоки программы. В слое модели вы создаете удобные абстракции вашей базы данных, в слое виды вы решаете, какие данные вы хотите показать, и в слое шаблоны вы создаете уже дизайн ваших страниц на основе html и добавляете в шаблоны немного логики с помощью языка Jinja — это из примера с фигурными скобками — {{ article.name }}.

Я тут не затронул довольно много важных тем — например связи между вашими моделями. У каждой статьи может быть один автор или несколько авторов — Django с легкостью справится с любым из перечисленных вариантов, и с помощью одной строки в Python вы сможете получить автора статьи или же коллекцию авторов в виде экземпляров класса Автор, созданного на основе models.Model.

Но откуда столько файлов?


Если вы создаете какое-то сложное приложение с кучей Моделей, видов и т.п. то это огромное количество кода надо как-то разбить на отдельные файлы. И файлы желательно организовать по папкам так, чтобы файл с моделями статьи был в той же папке что и виды статьи.
Вот тут приходит еще одна ключевая идея Django — приложения, которые заслуживают отдельного поста.