Django для веб-разработки: практическое введение с примерами кода

Раздел: Веб-разработка -> Django

Основы Django: создание первого проекта

Как создать проект Django с нуля?

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

Установка виртуального окружения и Django:

python -m venv venv
source venv/bin/activate  # Linux/macOS
venv\Scripts\activate  # Windows
pip install django

фреймворк python django (фреймворк django в python)

Создание проекта mysite:

django-admin startproject mysite
cd mysite

Python manage py (manage.py в django)

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

python manage.py startapp blog

Python run manage py (запуск manage.py в django)

Добавим приложение в settings.py (INSTALLED_APPS).

Определим простую модель в blog/models.py:

from django.db import models

class Post(models.Model):
    title = models.CharField(max_length=200)
    content = models.TextField()
    published_date = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

Python manage py migrate (команда migrate в django)

Создадим миграции и применим их:

python manage.py makemigrations
python manage.py migrate

Зарегистрируем модель в админке (blog/admin.py):

from django.contrib import admin
from .models import Post

admin.site.register(Post)

Создадим суперпользователя:

python manage.py createsuperuser

Запускаем сервер:

python manage.py runserver

Открываем http://127.0.0.1:8000/admin/ и проверяем работу.

Типичная проблема: ModuleNotFoundError: No module named 'django'. Возникает, если Django не установлен в активном виртуальном окружении. Решение: активировать виртуальное окружение и выполнить pip install django.

Другая проблема: при попытке применить миграции возникает django.db.utils.OperationalError: no such table. Это случается, если база данных SQLite повреждена или удалена. Решение: удалить файл db.sqlite3 и снова выполнить migrate.

Как использовать шаблон cookiecutter для ускорения старта?

Вместо ручного создания проекта можно применить cookiecutter-django. Это шаблон, включающий типовую структуру, настройки Docker, PostgreSQL, тестирование и т.д.

pip install cookiecutter
cookiecutter https://github.com/cookiecutter/cookiecutter-django

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

Проблема: при использовании cookiecutter может возникнуть конфликт имен, если проект уже существует. Решение: указать уникальное имя проекта при генерации.

Ошибка: TemplateNotFound из-за отсутствия интернета. Необходимо убедиться в доступности репозитория GitHub.

Как настроить Docker для разработки Django?

Использование Docker упрощает развертывание и изоляцию окружения. Пример простого Dockerfile:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "manage.py", "runserver", "0.0.0.0:8000"]

Файл docker-compose.yml для связки с PostgreSQL:

version: '3'
services:
  db:
    image: postgres:15
    environment:
      POSTGRES_DB: mydb
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
  web:
    build: .
    ports:
      - "8000:8000"
    depends_on:
      - db

Проблема: при запуске контейнера не удается подключиться к базе данных из-за неправильного хоста (localhost). Решение: в settings.py указать 'HOST': 'db' (имя сервиса).

Расширенные примеры работы с Django

Работа с формами и валидация

Создадим форму обратной связи с использованием ModelForm и обработаем её в представлении.

Файл forms.py приложения blog:

Пример
from django import forms
from .models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['title', 'content']
        widgets = {
            'content': forms.Textarea(attrs={'rows': 5}),
        }

Представление views.py:

Пример
from django.shortcuts import render, redirect
from .forms import PostForm

def create_post(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('post_list')
    else:
        form = PostForm()
    return render(request, 'blog/post_form.html', {'form': form})

Шаблон templates/blog/post_form.html:

Пример
<form method="post">
  {% csrf_token %}
  {{ form.as_p }}
  <button type="submit">Сохранить</button>
</form>

Результат: при отправке формы данные проходят валидацию, сохраняются в базу, и происходит перенаправление.

Использование generic-представлений ListView и DetailView

Заменим ручное представление на обобщённое:

Пример
from django.views.generic import ListView, DetailView
from .models import Post

class PostListView(ListView):
    model = Post
    template_name = 'blog/post_list.html'
    context_object_name = 'posts'

class PostDetailView(DetailView):
    model = Post
    template_name = 'blog/post_detail.html'

URL-паттерны (urls.py):

Пример
from django.urls import path
from .views import PostListView, PostDetailView

urlpatterns = [
    path('', PostListView.as_view(), name='post_list'),
    path('<int:pk>/', PostDetailView.as_view(), name='post_detail'),
]

Шаблон списка:

Пример
{% for post in posts %}
  <h2><a href="{% url 'post_detail' post.pk %}">{{ post.title }}</a></h2>
  <p>{{ post.content|truncatewords:20 }}</p>
{% endfor %}

Результат: список постов с ссылками, страница детального просмотра.

Добавление пагинации

В ListView пагинация настраивается очень просто:

Пример
class PostListView(ListView):
    model = Post
    paginate_by = 5
    # остальные атрибуты

В шаблоне:

Пример
<div class="pagination">
  <span class="step-links">
    {% if page_obj.has_previous %}
      <a href="?page=1">&laquo; первая</a>
      <a href="?page={{ page_obj.previous_page_number }}">предыдущая</a>
    {% endif %}
    <span class="current">Страница {{ page_obj.number }} из {{ page_obj.paginator.num_pages }}.</span>
    {% if page_obj.has_next %}
      <a href="?page={{ page_obj.next_page_number }}">следующая</a>
      <a href="?page={{ page_obj.paginator.num_pages }}">последняя &raquo;</a>
    {% endif %}
  </span>
</div>

Результат: на странице отображается не более 5 записей, внизу появляются ссылки для навигации.

REST API с Django REST Framework

Установка: pip install djangorestframework. Добавляем 'rest_framework' в INSTALLED_APPS. Создаём сериализатор:

Пример
from rest_framework import serializers
from .models import Post

class PostSerializer(serializers.ModelSerializer):
    class Meta:
        model = Post
        fields = '__all__'

Представление (views.py):

Пример
from rest_framework import generics
from .models import Post
from .serializers import PostSerializer

class PostListAPI(generics.ListCreateAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

class PostDetailAPI(generics.RetrieveUpdateDestroyAPIView):
    queryset = Post.objects.all()
    serializer_class = PostSerializer

URL-паттерны:

Пример
from django.urls import path
from .views import PostListAPI, PostDetailAPI

urlpatterns = [
    path('api/posts/', PostListAPI.as_view(), name='post-list'),
    path('api/posts/<int:pk>/', PostDetailAPI.as_view(), name='post-detail'),
]

Результат: полноценный REST API для модели Post с поддержкой GET, POST, PUT, PATCH, DELETE.

Использование сигналов для автоматических действий

Например, при создании поста автоматически генерировать slug. В signals.py:

Пример
from django.db.models.signals import pre_save
from django.dispatch import receiver
from django.utils.text import slugify
from .models import Post

@receiver(pre_save, sender=Post)
def create_slug(sender, instance, **kwargs):
    if not instance.slug:
        instance.slug = slugify(instance.title)

В apps.py приложения нужно импортировать сигналы:

Пример
from django.apps import AppConfig

class BlogConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'blog'

    def ready(self):
        import blog.signals

Результат: при сохранении поста slug заполняется автоматически из заголовка.

Фреймворк Django в Python - comments

En
фреймворк python django (python)