Простая установка Django 4.2: краткое руководство

Оглавление

Цель этой статьи - как можно быстрее начать использовать Django для создания веб-приложения и начать путь к готовому к производству приложению. В качестве демонстрации мы создадим простой блог для нашей компании под названием Foo.

Установка

При условии, что у вас настроен Python с помощью pip, установка проста. В результате будет установлен Django вместе с полезной командой, которая поможет быстро запустить проект.

pip install django

Следующая команда создает каталог проекта foo/ и формирует базовую структуру проекта и некоторые начальные файлы.

django-admin startproject foo

Давайте быстро пройдемся по каждому из созданных нами файлов:

manage.py - это утилита командной строки, которую предоставляет Django. Она поставляется с рядом команд, которые поддерживаются из коробки, некоторые из них мы рассмотрим позже. Некоторые приложения Django, которые вы сможете установить позже, добавят команды, доступные через эту утилиту, и в конечном итоге вы сможете добавлять свои собственные по мере необходимости.

foo/settings.py - это начальный пример файла настроек Django, который должен содержать всю конфигурацию вашего приложения. Если вы посмотрите на него, то увидите значения по умолчанию, которые настраивают ваше приложение для работы в локальной среде разработки.

foo/urls.py - это местоположение по умолчанию для конфигурации URL. По сути, это предоставляет Django правила маршрутизации запросов, которые получает ваше приложение.

foo/wsgi.py - это место, где находится собственно WSGI-приложение. При работе с Django в производстве необходимо использовать сервер типа uwsgi или green unicorn, серверы которых взаимодействуют с приложением, находящимся в этом файле. Теперь, когда мы создали проект, давайте попробуем его запустить. Чтобы запустить встроенный сервер разработки, выполните команду:

./manage.py runserver

Вы должны увидеть вывод, указывающий на используемые настройки и на то, где доступен сервер. Обратите внимание, что по умолчанию сервер доступен по адресу http://127.0.0.1:8000. Если перейти по этому адресу, то загрузится страница по умолчанию, сообщающая об успешной установке Django. Как видно из страницы, единственная причина, по которой вы видите эту страницу, заключается в том, что конфигурация по умолчанию, представленная в файле settings.py, имеет значение DEBUG = True. В противном случае при попытке перейти на эту страницу вы получили бы сообщение 404, поскольку конфигурация URL в urls.py не направляет этот путь ни к чему в вашем приложении.

Учет зависимостей

Прежде чем двигаться дальше, давайте создадим файл requirements.txt в базовом каталоге проекта, чтобы отслеживать все зависимости, которые мы устанавливаем с помощью pip. Пока мы установили только Django, поэтому наш файл requirements.txt будет выглядеть примерно так:

django==4.2

Создание приложения Django

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

./manage.py startapp blog

Команда startapp, как и startproject, создает для вас шаблонное приложение. Еще раз посмотрим на созданные нами файлы:

blog/__init__.py - это стандартный python __init__.py для превращения каталога в Python-модуль.

blog/admin.py - это файл для регистрации ваших моделей в Django Admin.

blog/apps.py содержит объект конфигурации Django Application. Он сообщает Django подробную информацию о вашем приложении.

blog/migrations/ - это папка для миграций вашей базы данных. В основном она управляется ORM Django. Как создавать миграции и применять их, мы рассмотрим позже.

blog/models.py - это место, куда следует помещать модели, использующие Django ORM. Это представляет собой интерфейс с вашим внутренним хранилищем данных.

blog/tests.py предоставляет место для размещения тестов для тестирования вашего приложения.

blog/views.py предоставляет определения для представлений ваших приложений. Именно здесь находится наша логика обработки запросов.

Регистрация приложения

Для того чтобы проект Django узнал о вашем приложении, вам необходимо зарегистрировать его, добавив в INSTALLED_APPS в settings.py. Теперь ваша INSTALLED_APPS должна выглядеть следующим образом:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

Определение Models

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

Мы определяем эти модели в blog/models.py:

from django.conf import settings
from django.db import models


class Topic(models.Model):
    slug = models.SlugField(max_length=50, unique=True)
    name = models.CharField(max_length=50)


class Post(models.Model):
    slug = models.SlugField(max_length=50, unique=True)
    title = models.CharField(max_length=50)
    body = models.TextField()
    published_on = models.DateTimeField(null=True, blank=True)
    topics = models.ManyToManyField('Topic', related_name='posts')


class Comment(models.Model):
    post = models.ForeignKey(
        'Post', on_delete=models.CASCADE, related_name='comments'
    )
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE,
        related_name='comments'
    )
    body = models.TextField()
    commented_on = models.DateTimeField(auto_now_add=True)

Здесь много деталей, но в основном мы определили объекты, описанные выше, а также связь между этими объектами и пользовательской моделью Django, используемой при аутентификации. Определив модели, мы хотим сгенерировать миграции базы данных, чтобы создать таблицы базы данных.

Для генерации миграций можно воспользоваться командой makemigrations Django:

./manage.py makemigrations

При выполнении этой команды вы увидите краткую информацию о произведенных изменениях и имена созданных файлов миграций. В данном случае это должен быть только один файл, который будет являться начальной миграцией для нашего блог-приложения. Открыв blog/migrations/0001_initial.py, вы увидите, какие шаги, по мнению Django, необходимо предпринять для изменения текущего состояния базы данных на новое заданное состояние. Чтобы применить эти изменения, мы используем команду migrate:

./manage.py migrate

Поскольку мы впервые выполняем команду migrate, будет запущен и ряд других миграций. Эти миграции происходят из некоторых встроенных приложений Django, которые включают поддержку:

  • Модель пользователя аутентификации и прав доступа
  • Модели отслеживания администраторов
  • Фреймворк ContentTypes
  • Сессии

Если посмотреть на базовый каталог проекта, то можно заметить новый файл: db.sqlite3. По умолчанию Django использует SQLite3 в качестве внутреннего хранилища данных, которое записывает файл базы данных в текущий рабочий каталог.

Управление данными

Теперь, когда мы определили модель данных и создали таблицы базы данных, необходимо найти способ управления данными в нашей базе. Админ Django - это невероятно быстрый способ создания интерфейса для управления данными, хранящимися в ваших моделях. В разделе blog/admin.py мы можем быстро зарегистрировать наши модели, чтобы сделать интерфейс управления доступным в админке Django:

from django.contrib import admin

from .models import Comment, Post, Topic


admin.site.register(Comment)
admin.site.register(Post)
admin.site.register(Topic)

Теперь, зарегистрировав наши модели, мы можем перейти к админке Django, которая по умолчанию (если смотреть на foo/urls.py) размещена по адресу /admin, а на нашем локальном сервере доступна по адресу http://localhost:8000/admin/. Однако при попытке доступа к админке происходит перенаправление на экран входа в систему. В нашей системе еще не создан пользователь, поэтому мы не можем войти в систему, поэтому давайте создадим нового пользователя с правами администратора.

Опять же, в Django для этого есть команда:

./manage.py createsuperuser

Вам будет предложено ввести имя пользователя, e-mail и пароль (дважды). После создания нового суперпользователя (admin) можно войти в систему и изучить интерфейс. Вы увидите, что, не меняя ничего, есть раздел Authentication and Authorization, который можно использовать для управления системой аутентификации и разрешений Django, в которой есть Users and Groups. Далее вы найдете раздел для нашего блог-приложения, который поддерживает интерфейс для создания, редактирования и удаления тем, постов и комментариев.

Презентация своих сообщений

Теперь, когда мы можем создавать и хранить данные, мы хотим создать страницу, которая предоставляет список всех наших сообщений, и страницу, которая отображает одно сообщение, позволяя пользователям комментировать его. Для каждой страницы необходимо написать представление (для обработки запроса), шаблон (для отображения html) и конфигурацию url (для маршрутизации запроса).

Виды

Для начала определим два представления в blog/views.py:

from django.shortcuts import redirect, render, reverse
from django.views.generic import DetailView, ListView

from .forms import CommentForm
from .models import Post


class PostListView(ListView):
    model = Post


class PostDetailView(DetailView):
    model = Post

    def post(self, request, slug=None):
        form = CommentForm(data=request.POST)
        if form.is_valid():
            form.save()
            return redirect(
                reverse('blog:post_detail', kwargs={'slug': slug})
            )
        return self.get(request, slug=slug)

    def get_context_data(self, **kwargs):
        ctx = super(PostDetailView, self).get_context_data(**kwargs)
        ctx['form'] = CommentForm(
            initial={
                'post': self.object,
                'user': self.request.user
            }
        )
        return ctx

Django предоставляет несколько общих представлений, которые обрабатывают большую часть необходимой нам логики. Представление ListView позволяет указать модель и получить список всех объектов в этой таблице для использования в вашем шаблоне. DetailView позволяет указать модель и получить один объект из таблицы, заданный уникальным идентификатором в конфигурации url. В данном случае мы будем использовать slug, определенный для модели Post.

Поскольку мы также хотим поддерживать комментирование, мы переопределяем метод get_context_data, чтобы добавить CommentForm, определенный в blogs/forms.py, в контекст, который DetailView будет передавать шаблонизатору для отрисовки шаблона. Нам также необходимо добавить метод post к DetailView, который использует CommentForm для создания комментариев:

from django import forms

from .models import Comment


class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('post', 'user', 'body')
        widgets = {
            'post': forms.HiddenInput(),
            'user': forms.HiddenInput()
        }

Templates

Для того, чтобы реально вывести HTML, мы хотим использовать шаблоны. По умолчанию встроенные представления Django будут искать шаблон списка постов по адресу blog/templates/blog/post_list.html и шаблон деталей постов по адресу blog/templates/blog/post_detail.html. Чтобы избежать дублирования кода, мы создадим базовый шаблон и расширим его, чтобы создать шаблоны для двух наших страниц.

Сначала введите blog/templates/blog/base.html:

<!DOCTYPE html>
<html>
  <head>
    <title>{% block title %}Foo Blog{% endblock title %}</title>
  </head>
  </head>
  <body>
    {% block content %}
    {% endblock content %}
  </body>
</html>

Теперь мы можем создать HTML для представления списка в blog/templates/blog/post_list.html:

{% extends "blog/base.html" %}

{% block content %}
<h1>Foo Blog</h1>
<div>
  {% for post in object_list %}
    <div>==========================================================</div>
    <div>Posted on {{ post.published_on }}</div>
    <div><h3>{{ post.title }}</h3></div>
    <div>{{ post.snippet }}...<a href="{% url "blog:post_detail" slug=post.slug %}">continue reading.</a></div>
    <div>==========================================================</div>
    <br/>
  {% endfor %}
</div>
{% endblock content %}

А HTML для детального представления в blog/templates/blog/post_detail.html имеет вид:

{% extends "blog/base.html" %}

{% block content %}
<h3>{{ object.title }}</h3>
<h4>Topics</h4>
<ul>
  {% for topic in object.topics.all %}
    <li>{{ topic.name }}</li>
  {% endfor %}
</ul>
<div>Posted on {{ object.published_on }}</div>
<br/>
<div>{{ object.body }}</div>
<br/>
<div>
  <h4>Comments</h4>
  {% for comment in object.comments.all %}
    <div>---------------------------------------------------</div>
    <div>{{ comment.body }}</div>
    <div>Commented on {{ comment.commented_on }}</div>
    <div>---------------------------------------------------</div>
  {% endfor %}
</div>
{% if user.is_authenticated %}
<div>
  <h4>Leave a Comment</h4>
  <form method="post">
    {% csrf_token %}
    <div>{{ form.post }}</div>
    <div>{{ form.user }}</div>
    <div>{{ form.body }}</div>
    <button>Submit</button>
  </form>
</div>
{% endif %}
<br/>
<div><a href="{% url "blog:post_list" %}"><< Back to Post List</a></div>
{% endblock content %}

Конфигурация URL

Наконец, мы хотим направить запросы к нашим представлениям, чтобы сделать их доступными в нашем веб-приложении. Поскольку мы можем захотеть, чтобы этот блог был только отдельной частью нашего проекта (и веб-приложения), мы можем сохранить все хорошо разделенным и модульным, определив конфигурацию url блога в приложении блога и включив эту конфигурацию в конфигурацию url проекта. Начнем с того, что создадим blog/urls.py:

from django.urls import path

from .views import PostDetailView, PostListView

app_name = 'blog'

urlpatterns = [
    path('', PostListView.as_view(), name='post_list'),
    path('/', PostDetailView.as_view(), name='post_detail'),
]

Затем измените foo/urls.py:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path('admin/', admin.site.urls),
    path('blog/', include('blog.urls', namespace='blog')),
]

Теперь наш блог доступен по адресу http://localhost:8000/blog/, а каждая запись будет доступна по адресу http://localhost:8000/blog/<slug >/.

Итоги

При минимальных затратах времени и усилий мы реализовали простейший блог, который хоть и не имеет стилистики, но вполне функционален. Используя встроенный в Django интерфейс администратора, мы можем управлять всеми данными: темами, постами и комментариями. Данные сохраняются через определения моделей с помощью ORM Django. Наконец, мы настраиваем некоторые маршруты, представления и шаблоны, чтобы сделать наши сообщения общедоступными в нашем веб-приложении.

Что дальше?

Созданное нами приложение для ведения блога является функциональным, но базовым. В идеале мы хотели бы добавить в наши шаблоны дизайн/стилистику, чтобы представить наши записи в более красивом виде. Мы также хотели бы иметь редактор в нашем административном инструменте с возможностью применения форматирования, которое будет транслироваться в html для отображения записи. Возможно, нам понадобится возможность фильтрации по темам или поиска конкретных сообщений. Каждое из этих дополнений легко реализуемо либо с помощью сторонних расширений для Django, либо в рамках самого фреймворка. Наконец, блог необходимо будет развернуть в производственной среде, для чего потребуется поддержка производственных настроек в приложении, решение для хостинга, механизмы развертывания, производственные веб-серверы и серверы приложений для размещения приложения, а также виртуальный или физический сервер для размещения всего этого программного обеспечения.

Вернуться на верх