Знакомство с Django

Поскольку Django был разработан в бурлящей среде новостного агентства, он призван сделать веб-разработку простой и быстрой. Далее представлен вводный обзор того, как можно писать веб-приложения при помощи Django.

Цель данного документа: предоставить вам достаточное количество технической информации для понимания основ работы Django, но следует иметь ввиду, что этот обзор не является учебником или справочником – хотя у нас всё это есть! Когда вы будете готовы к созданию своего первого проекта, вы можете начать с учебного руководства или окунуться в море подробнейшей информации.

Проектирование модели

Хотя вы вполне можете обойтись без использования базы данных, Django предоставляет object-relational mapper для описания формата БД в виде кода на языке Python.

Синтаксис моделей данных предлагает множество различных способов представления ваших данных, что помогает решать стандартные задачи по использованию БД. Вот небольшой пример:

mysite/news/models.py
from django.db import models

class Reporter(models.Model):
    full_name = models.CharField(max_length=70)

    def __str__(self):
        return self.full_name

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)

    def __str__(self):
        return self.headline

Настройка базы данных

Next, run the Django command-line utilities to create the database tables automatically:

$ python manage.py makemigrations
$ python manage.py migrate
...\> py manage.py makemigrations
...\> py manage.py migrate

The makemigrations command looks at all your available models and creates migrations for whichever tables don’t already exist. migrate runs the migrations and creates tables in your database, as well as optionally providing much richer schema control.

Наслаждайтесь свободным API

With that, you’ve got a free, and rich, Python API to access your data. The API is created on the fly, no code generation necessary:

# Import the models we created from our "news" app
>>> from news.models import Article, Reporter

# No reporters are in the system yet.
>>> Reporter.objects.all()
<QuerySet []>

# Create a new Reporter.
>>> r = Reporter(full_name='John Smith')

# Save the object into the database. You have to call save() explicitly.
>>> r.save()

# Now it has an ID.
>>> r.id
1

# Now the new reporter is in the database.
>>> Reporter.objects.all()
<QuerySet [<Reporter: John Smith>]>

# Fields are represented as attributes on the Python object.
>>> r.full_name
'John Smith'

# Django provides a rich database lookup API.
>>> Reporter.objects.get(id=1)
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__startswith='John')
<Reporter: John Smith>
>>> Reporter.objects.get(full_name__contains='mith')
<Reporter: John Smith>
>>> Reporter.objects.get(id=2)
Traceback (most recent call last):
    ...
DoesNotExist: Reporter matching query does not exist.

# Create an article.
>>> from datetime import date
>>> a = Article(pub_date=date.today(), headline='Django is cool',
...     content='Yeah.', reporter=r)
>>> a.save()

# Now the article is in the database.
>>> Article.objects.all()
<QuerySet [<Article: Django is cool>]>

# Article objects get API access to related Reporter objects.
>>> r = a.reporter
>>> r.full_name
'John Smith'

# And vice versa: Reporter objects get API access to Article objects.
>>> r.article_set.all()
<QuerySet [<Article: Django is cool>]>

# The API follows relationships as far as you need, performing efficient
# JOINs for you behind the scenes.
# This finds all articles by a reporter whose name starts with "John".
>>> Article.objects.filter(reporter__full_name__startswith='John')
<QuerySet [<Article: Django is cool>]>

# Change an object by altering its attributes and calling save().
>>> r.full_name = 'Billy Goat'
>>> r.save()

# Delete an object with delete().
>>> r.delete()

Динамический административный интерфейс: это не просто строительный материал – это готовый дом

Once your models are defined, Django can automatically create a professional, production ready administrative interface – a website that lets authenticated users add, change and delete objects. The only step required is to register your model in the admin site:

mysite/news/models.py
from django.db import models

class Article(models.Model):
    pub_date = models.DateField()
    headline = models.CharField(max_length=200)
    content = models.TextField()
    reporter = models.ForeignKey(Reporter, on_delete=models.CASCADE)
mysite/news/admin.py
from django.contrib import admin

from . import models

admin.site.register(models.Article)

The philosophy here is that your site is edited by a staff, or a client, or maybe just you – and you don’t want to have to deal with creating backend interfaces only to manage content.

Обычным рабочим моментом при создании сайта на Django, является написание моделей и получение прав администратора для того, чтобы как можно скорее приступить к работе. Так ваши сотрудники (или клиенты) могут сразу же начать наполнение сайта данными, а вы параллельно продолжите подготавливать сайт для публикации.

Проектирование схемы URL

Красивая, элегантная схема URL является важной составляющей высококачественного веб-приложения. Django поощряет создание красивых схем URL и не захламляет их мусором, подобным .php или же .asp.

To design URLs for an app, you create a Python module called a URLconf. A table of contents for your app, it contains a mapping between URL patterns and Python callback functions. URLconfs also serve to decouple URLs from Python code.

Вот таким образом может выглядеть схема URL для классов Reporter/Article, представленных выше:

mysite/news/urls.py
from django.urls import path

from . import views

urlpatterns = [
    path('articles/<int:year>/', views.year_archive),
    path('articles/<int:year>/<int:month>/', views.month_archive),
    path('articles/<int:year>/<int:month>/<int:pk>/', views.article_detail),
]

Код выше описывает URL-ы для вызова соответствующих функций Python (соответствующего представления, «views»). Теги с параметрами используются для «захвата» значения из URL-адреса. Когда пользователь запрашивает страницу, Django проходит по всем шаблонам по порядку и останавливается на первом подходящем (если ни один из шаблонов не подошёл, Django вызовет исключение 404.) Это происходит мгновенно, поскольку регулярные выражения компилируются ещё во время загрузки.

После того, как соответствующий шаблон найден, Django импортирует и вызывает представление, которое является по сути простой функцией на Python. Каждое представление передаёт объект запроса – он содержит возвращаемые метаданные – и значения, захваченные шаблонами.

К примеру, если пользователь запросил URL «/articles/2005/05/39323/», Django должен вернуть функцию news.views.article_detail(request, year=2005, month=5, pk=39323).

Написание представлений

Каждое представление отвечает за выполнение одной из двух вещей: возвращение объекта HttpResponse, представляющего содержимое запрашиваемой страницы, или вызов исключения такого как Http404. Остальное зависит от вас.

Как правило, представление извлекает данные в соответствии с заданными параметрами, загружает шаблон и отображает этот шаблон вместе с полученными данными. Это пример представления year_archive, представленного выше:

mysite/news/views.py
from django.shortcuts import render

from .models import Article

def year_archive(request, year):
    a_list = Article.objects.filter(pub_date__year=year)
    context = {'year': year, 'article_list': a_list}
    return render(request, 'news/year_archive.html', context)

В примере используется язык шаблонов Django, который имеет несколько сильных особенностей, но вместе с тем остаётся простым в использовании даже для не-программистов.

Проектирование шаблонов

Код, представленный выше, возвращает шаблон news/year_archive.html.

Django включает пути поиска по шаблонам, что позволяет свести к минимуму избыточность html-кода. В настройках Django нужно указать список каталогов, откуда Django сможет загружать шаблоны. Это делается с помощью настройки DIRS. Если шаблон не будет найден в первом каталоге, Django проверит второй и все последующие.

Скажем, шаблон news/year_archive.html был найден. Вот как он может выглядеть:

mysite/news/templates/news/year_archive.html
{% extends "base.html" %}

{% block title %}Articles for {{ year }}{% endblock %}

{% block content %}
<h1>Articles for {{ year }}</h1>

{% for article in article_list %}
    <p>{{ article.headline }}</p>
    <p>By {{ article.reporter.full_name }}</p>
    <p>Published {{ article.pub_date|date:"F j, Y" }}</p>
{% endfor %}
{% endblock %}

Переменные всегда окружены двумя фигурными скобками. {{ article.headline }} означает «вывести переменную, хранящую заголовок статьи.» Хотя точка используется не только для доступа к атрибутам: с её помощью можно провести поиск в словаре, поиск индекса и вызов функции.

Примечательно, что {{ article.pub_date|date:"F j, Y" }} использует Unix-стиль «pipe» (символ вертикальной черты «|»). Это называется шаблонным фильтром и это хороший способ для фильтрации значений переменной. В примере фильтр даты приводит объект datetime к нужному виду (как нахождение функции даты в PHP).

Вы можете последовательно применить столько фильтров, сколько вам будет нужно. Вы можете писать собственные шаблонные фильтры. Вы можете писать собственные шаблонные теги, которые будут неявно выполнять ваш код.

Наконец, Django использует концепцию «наследования шаблонов»: это достигается путём включения базового шаблона {% extends "base.html" %}. И это значит, что первым будет загружен шаблон „base“, в котором определено множество различных блоков, которые в свою очередь также могут содержать в себе какие-то блоки. Короче говоря, это позволяет намного сократить количество html-шаблонов страниц: каждый новый шаблон должен включать уникальные элементы, присущие только ему.

Базовый шаблон «base.html», включающий использование статических файлов, может выглядеть следующим образом:

mysite/templates/base.html
{% load static %}
<html>
<head>
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <img src="{% static "images/sitelogo.png" %}" alt="Logo">
    {% block content %}{% endblock %}
</body>
</html>

Simplistically, it defines the look-and-feel of the site (with the site’s logo), and provides «holes» for child templates to fill. This means that a site redesign can be done by changing a single file – the base template.

It also lets you create multiple versions of a site, with different base templates, while reusing child templates. Django’s creators have used this technique to create strikingly different mobile versions of sites by only creating a new base template.

Обратите внимание на то, что вы можете не использовать язык шаблонов Django, если отдаёте предпочтение какому-то иному. Хотя язык шаблонов Django как нельзя лучше подходит при создании моделей Django, никто не заставляет вас использовать его. Если уж на то пошло, знайте, что вы даже вправе не пользоваться API баз данных Django. Вы можете использовать другой уровень абстракции базы данных, вы можете читать XML-файлы, вы можете читать файлы с диска, да и вообще делать всё, что угодно. Каждая часть Django – модели, представления, шаблоны – отделены друг от друга.

Это просто вершина айсберга

Это был только краткий обзор возможностей Django. Вот ещё несколько полезных особенностей, о которых следовало бы знать:

  • Система кэширования, интегрированная с memcached или другими бэкэндами кэширования.
  • A syndication framework that lets you create RSS and Atom feeds by writing a small Python class.
  • More attractive automatically-generated admin features – this overview barely scratched the surface.

The next steps are for you to download Django, read the tutorial and join the community. Thanks for your interest!