Django остаётся одним из самых популярных фреймворков для бэкенд-разработки на Python. По данным опроса JetBrains Developer Ecosystem Survey 2025, Django используют 48% Python-разработчиков, работающих с веб-фреймворками. Но даже опытные разработчики тратят до 30% времени на написание шаблонного кода: сериализаторов, представлений, тестов и конфигураций. Эта подборка промтов — не магическая таблетка, а инструмент, который помогает быстрее генерировать качественные заготовки. Каждый промт спроектирован так, чтобы вы получали не просто код, а готовый к интеграции модуль с учётом лучших практик Django (DRY, Fat Models, Thin Views).
1. Модель с кастомными методами и менеджером
Задача: Создать модель Order с полями (customer, total, status, created_at), кастомным менеджером для фильтрации активных заказов и методом для расчёта налога.
Промт:
Создай модель Django для заказа (Order) с полями: customer (ForeignKey на User), total (DecimalField), status (CharField с выбором из 'pending', 'paid', 'cancelled'), created_at (DateTimeField auto_now_add). Добавь кастомный менеджер ActiveOrdersManager, который фильтрует заказы со статусом 'paid'. Реализуй метод calculate_tax(self, rate=0.2), который возвращает сумму налога. Используй Python 3.11+, Django 5.0, типизованные аннотации.
Пример результата (фрагмент):
from django.db import models
from django.conf import settings
from typing import Literal
class ActiveOrdersManager(models.Manager):
def get_queryset(self) -> models.QuerySet:
return super().get_queryset().filter(status='paid')
class Order(models.Model):
class Status(models.TextChoices):
PENDING = 'pending', 'Ожидает'
PAID = 'paid', 'Оплачен'
CANCELLED = 'cancelled', 'Отменён'
customer = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name='orders'
)
total = models.DecimalField(max_digits=10, decimal_places=2)
status = models.CharField(
max_length=10,
choices=Status.choices,
default=Status.PENDING
)
created_at = models.DateTimeField(auto_now_add=True)
objects = models.Manager()
active_objects = ActiveOrdersManager()
def calculate_tax(self, rate: float = 0.2) -> float:
return float(self.total) * rate
def __str__(self) -> str:
return f'Order #{self.pk} by {self.customer.username}'
Пояснение: Такой промт даёт модель с разделением ответственности: бизнес-логика в методах (calculate_tax), кастомные выборки через менеджеры. Это соответствует принципу Fat Models, рекомендованному в документации Django (https://docs.djangoproject.com/en/5.0/topics/db/managers/). Не забудьте заменить settings.AUTH_USER_MODEL на свою модель пользователя.
2. CBV для CRUD с пагинацией и поиском
Задача: Написать Class-Based View для списка товаров с пагинацией (20 элементов на страницу), поиском по названию и фильтрацией по категории.
Промт:
Создай Django ListView для модели Product. Включи пагинацию на 20 элементов, добавь поиск по полю 'name' через GET-параметр 'q', и фильтрацию по внешнему ключу 'category' через параметр 'category_id'. Используй generic-класс ListView и миксины. Выведи результат с контекстом: page_obj, search_query, selected_category.
Пример результата:
from django.views.generic import ListView
from django.db.models import Q
from .models import Product, Category
class ProductListView(ListView):
model = Product
template_name = 'catalog/product_list.html'
context_object_name = 'products'
paginate_by = 20
def get_queryset(self):
queryset = super().get_queryset()
search_query = self.request.GET.get('q', '').strip()
category_id = self.request.GET.get('category_id')
if search_query:
queryset = queryset.filter(name__icontains=search_query)
if category_id:
queryset = queryset.filter(category_id=category_id)
return queryset.select_related('category').only(
'name', 'price', 'category__name'
)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['search_query'] = self.request.GET.get('q', '')
context['selected_category'] = self.request.GET.get('category_id')
context['categories'] = Category.objects.all()
return context
Пояснение: Использование select_related и only уменьшает количество запросов к БД. Это особенно важно для страниц каталога. DTL-шаблон может использовать page_obj для навигации. Подход соответствует DRY: вы не пишете пагинацию вручную.
3. DRF ViewSet с фильтрацией и сортировкой
Задача: Создать ViewSet для модели Article с полями title, content, author, created_at. Реализовать фильтрацию по автору (через django-filter), сортировку по дате и поиск по заголовку.
Промт:
Напиши DRF ViewSet для модели Article. Используй ModelViewSet, подключи django-filter для фильтрации по полю author (email), добавь возможность сортировки по created_at через OrderingFilter, и поиск по title через SearchFilter. Укажи permission_classes = [IsAuthenticatedOrReadOnly].
Пример результата:
from rest_framework import viewsets, filters
from django_filters.rest_framework import DjangoFilterBackend
from .models import Article
from .serializers import ArticleSerializer
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.select_related('author').all()
serializer_class = ArticleSerializer
permission_classes = [IsAuthenticatedOrReadOnly]
filter_backends = [
DjangoFilterBackend,
filters.SearchFilter,
filters.OrderingFilter
]
filterset_fields = ['author__email']
search_fields = ['title']
ordering_fields = ['created_at', 'title']
ordering = ['-created_at']
Пояснение: DRF ViewSet с бэкендами фильтрации — стандарт в индустрии. Согласно документации DRF (https://www.django-rest-framework.org/api-guide/filtering/), такой подход сокращает код на 40% по сравнению с ручной реализацией. select_related предотвращает N+1 проблему.
4. Кастомный middleware для логирования запросов
Задача: Написать middleware, который логирует метод, путь и время выполнения каждого HTTP-запроса.
Промт:
Создай Django middleware, который для каждого входящего запроса записывает в лог (logging.info) метод, путь и время обработки в миллисекундах. Используй process_view или __call__ для совместимости с Django 5.0. Лог должен быть структурированным: 'METHOD PATH - Xms'.
Пример результата:
import time
import logging
from django.utils.deprecation import MiddlewareMixin
logger = logging.getLogger(__name__)
class RequestLoggingMiddleware(MiddlewareMixin):
def process_view(self, request, view_func, view_args, view_kwargs):
request._start_time = time.time()
return None
def process_response(self, request, response):
if hasattr(request, '_start_time'):
duration = (time.time() - request._start_time) * 1000
logger.info(
f'{request.method} {request.get_full_path()} - {duration:.0f}ms'
)
return response
Пояснение: Middleware — мощный механизм Django. Этот пример использует MiddlewareMixin для обратной совместимости. Логирование времени помогает выявлять медленные эндпоинты. Настройте уровень логирования в settings.py.
5. Кастомный менеджер с агрегацией
Задача: Создать менеджер для модели Product, который возвращает топ-10 самых продаваемых товаров за последние 30 дней.
Промт:
Добавь в модель Product кастомный менеджер TopSalesManager с методом top_selling(days=30, limit=10), который через related_name 'order_items' (модель OrderItem с полем quantity) агрегирует сумму quantity, группирует по product_id, сортирует по убыванию и возвращает limit записей. Используй annotate и Sum.
Пример результата:
from django.db import models
from django.db.models import Sum
from django.utils import timezone
from datetime import timedelta
class TopSalesManager(models.Manager):
def top_selling(self, days: int = 30, limit: int = 10):
cutoff_date = timezone.now() - timedelta(days=days)
return self.get_queryset().filter(
order_items__created_at__gte=cutoff_date
).annotate(
total_sold=Sum('order_items__quantity')
).order_by('-total_sold')[:limit]
Пояснение: Агрегация на уровне менеджера — пример паттерна QuerySet reuse. Вызов Product.objects.top_selling() возвращает готовый QuerySet. Обратите внимание: предполагается, что модель OrderItem имеет поле created_at и product как ForeignKey с related_name='order_items'.
6. Сериализатор с вложенными объектами и валидацией
Задача: Написать DRF-сериализатор для заказа, включающий вложенные позиции и кастомную валидацию минимальной суммы.
Промт:
Создай сериализатор OrderSerializer для модели Order с полями id, customer (email), total, items (вложенный список OrderItemSerializer). OrderItemSerializer должен содержать product (name, price), quantity, subtotal (calculated field). Добавь валидацию: total не может быть меньше 10. Используя SerializerMethodField для subtotal и PrimaryKeyRelatedField для customer.
Пример результата:
from rest_framework import serializers
from .models import Order, OrderItem
class OrderItemSerializer(serializers.ModelSerializer):
product_name = serializers.CharField(source='product.name', read_only=True)
product_price = serializers.DecimalField(
source='product.price', max_digits=10, decimal_places=2, read_only=True
)
subtotal = serializers.SerializerMethodField()
class Meta:
model = OrderItem
fields = ['id', 'product', 'product_name', 'product_price',
'quantity', 'subtotal']
def get_subtotal(self, obj):
return float(obj.product.price) * obj.quantity
class OrderSerializer(serializers.ModelSerializer):
items = OrderItemSerializer(many=True, read_only=True)
customer_email = serializers.EmailField(source='customer.email', read_only=True)
class Meta:
model = Order
fields = ['id', 'customer', 'customer_email', 'total', 'items', 'created_at']
def validate_total(self, value):
if value < 10:
raise serializers.ValidationError('Сумма заказа не может быть менее 10')
return value
Пояснение: Вложенные сериализаторы — стандарт для REST API. source позволяет извлекать данные из связанных моделей без дополнительных запросов. Валидация на уровне сериализатора гарантирует целостность данных.
7. Сигнал для создания профиля при регистрации
Задача: Автоматически создавать профиль пользователя при создании экземпляра User.
Промт:
Напиши Django сигнал post_save для модели User, который при создании нового пользователя (created=True) создаёт связанную модель Profile с полями bio (TextField, blank=True) и avatar (ImageField, upload_to='avatars/'). Используй @receiver декоратор. Обработай случай, если Profile уже существует (update_or_create).
Пример результата:
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.contrib.auth.models import User
from .models import Profile
@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
else:
instance.profile.save()
Пояснение: Сигналы — ключевой паттерн для поддержания согласованности данных. Альтернатива — переопределение save() модели User, но сигналы менее инвазивны. Подробнее в документации: https://docs.djangoproject.com/en/5.0/topics/signals/.
8. Кастомная команда управления для очистки старых записей
Задача: Создать management command, которая удаляет неоплаченные заказы старше 7 дней.
Промт:
Напиши Django management command 'cleanup_orders', которая удаляет все заказы со статусом 'pending', созданные более 7 дней назад. Используй BaseCommand, добавь аргумент --dry-run для вывода количества заказов без удаления. Логируй результат через self.stdout.
Пример результата:
from django.core.management.base import BaseCommand
from django.utils import timezone
from datetime import timedelta
from orders.models import Order
class Command(BaseCommand):
help = 'Удаляет неоплаченные заказы старше 7 дней'
def add_arguments(self, parser):
parser.add_argument(
'--dry-run',
action='store_true',
help='Показать количество заказов без удаления'
)
def handle(self, *args, **options):
cutoff = timezone.now() - timedelta(days=7)
orders = Order.objects.filter(
status='pending',
created_at__lt=cutoff
)
count = orders.count()
if options['dry_run']:
self.stdout.write(f'Будет удалено {count} заказов')
return
orders.delete()
self.stdout.write(self.style.SUCCESS(f'Удалено {count} заказов'))
Пояснение: Management commands — стандартный способ автоматизации задач в Django. --dry-run — хорошая практика для опасных операций. Запуск через python manage.py cleanup_orders.
9. Пагинация в DRF с кастомным ответом
Задача: Настроить пагинацию для API так, чтобы ответ содержал next, previous, count и results, но с добавлением поля total_pages.
Промт:
Создай кастомный класс пагинации для DRF, наследующий PageNumberPagination. Переопредели get_paginated_response, чтобы включить поле total_pages. Установи page_size = 10.
Пример результата:
from rest_framework.pagination import PageNumberPagination
from rest_framework.response import Response
from math import ceil
class CustomPagination(PageNumberPagination):
page_size = 10
page_size_query_param = 'page_size'
max_page_size = 100
def get_paginated_response(self, data):
total_pages = ceil(self.page.paginator.count / self.page_size)
return Response({
'count': self.page.paginator.count,
'total_pages': total_pages,
'next': self.get_next_link(),
'previous': self.get_previous_link(),
'results': data
})
Пояснение: Кастомная пагинация улучшает UX для клиентов API. Поле total_pages упрощает построение интерфейса пагинации на фронтенде. Подключите через DEFAULT_PAGINATION_CLASS в settings.
10. Тесты для модели и API
Задача: Написать тесты для модели Order и её методов, а также для эндпоинта списка заказов.
Промт:
Создай тестовый класс для модели Order: проверь создание заказа, работу метода calculate_tax и кастомного менеджера active_objects. Затем напиши тест для API (APITestCase) — проверь, что GET /api/orders/ возвращает 200 и содержит только активные заказы для аутентифицированного пользователя.
Пример результата:
from django.test import TestCase
from django.contrib.auth.models import User
from .models import Order
from decimal import Decimal
class OrderModelTest(TestCase):
def setUp(self):
self.user = User.objects.create_user(username='testuser', password='12345')
self.order = Order.objects.create(
customer=self.user,
total=Decimal('100.00'),
status='paid'
)
def test_calculate_tax(self):
self.assertEqual(self.order.calculate_tax(0.2), 20.0)
def test_active_manager(self):
Order.objects.create(customer=self.user, total=50, status='pending')
self.assertEqual(Order.active_objects.count(), 1)
Пояснение: Тесты — основа надёжности. Встроенный TestCase Django покрывает базу данных. Для API используйте rest_framework.test.APITestCase. Подробнее: https://docs.djangoproject.com/en/5.0/topics/testing/.
11. Админка с InlineModelAdmin и кастомными действиями
Задача: Настроить админку для модели Order, добавив inline для OrderItem и действие для массовой смены статуса на 'cancelled'.
Промт:
Создай ModelAdmin для Order: отобрази поля id, customer, total, status, created_at. Добавь TabularInline для OrderItem. Реализуй action 'mark_as_cancelled', который меняет статус выбранных заказов на 'cancelled' и выводит сообщение об успехе.
Пример результата:
from django.contrib import admin
from .models import Order, OrderItem
class OrderItemInline(admin.TabularInline):
model = OrderItem
extra = 1
@admin.action(description='Отметить как отменённые')
def mark_as_cancelled(modeladmin, request, queryset):
queryset.update(status='cancelled')
@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
list_display = ['id', 'customer', 'total', 'status', 'created_at']
list_filter = ['status', 'created_at']
search_fields = ['customer__username', 'id']
inlines = [OrderItemInline]
actions = [mark_as_cancelled]
Пояснение: Inline-редактирование ускоряет работу с заказами. Кастомные действия — мощный инструмент для массовых операций. Документация: https://docs.djangoproject.com/en/5.0/ref/contrib/admin/actions/.
12. Миграция данных с помощью RunPython
Задача: Написать миграцию, которая заполняет поле slug для всех существующих статей на основе заголовка.
Промт:
Создай пустую миграцию Django, которая использует RunPython для генерации slug для всех статей, у которых slug пустой. Используй функцию slugify из django.utils.text. Обработай дубликаты, добавляя суффикс '-1', '-2' и т.д.
Пример результата:
from django.db import migrations
from django.utils.text import slugify
def generate_slugs(apps, schema_editor):
Article = apps.get_model('blog', 'Article')
for article in Article.objects.filter(slug__isnull=True):
base_slug = slugify(article.title)[:50]
slug = base_slug
counter = 1
while Article.objects.filter(slug=slug).exclude(pk=article.pk).exists():
slug = f'{base_slug}-{counter}'
counter += 1
article.slug = slug
article.save(update_fields=['slug'])
class Migration(migrations.Migration):
dependencies = [
('blog', '0001_initial'),
]
operations = [
migrations.RunPython(generate_slugs),
]
Пояснение: Data migrations безопаснее, чем скрипты, так как выполняются в транзакции. Используйте apps.get_model, а не прямой импорт — это гарантирует корректную работу с историческими состояниями моделей.
13. Настройка CORS в DRF
Задача: Разрешить кросс-доменные запросы для API, ограничив список разрешённых источников.
Промт:
Настрой CORS для Django-приложения, используя django-cors-headers. Разреши запросы только с доменов https://frontend.example.com и http://localhost:3000. Разреши все методы и заголовки для CORS-запросов.
Пример результата (в settings.py):
INSTALLED_APPS = [
...
'corsheaders',
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
...
]
CORS_ALLOWED_ORIGINS = [
'https://frontend.example.com',
'http://localhost:3000',
]
CORS_ALLOW_METHODS = [
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
]
CORS_ALLOW_HEADERS = [
'accept',
'authorization',
'content-type',
'x-csrftoken',
]
Пояснение: Без настройки CORS фронтенд на другом домене не сможет делать запросы к API. django-cors-headers — стандартное решение. Всегда ограничивайте origins в продакшене.
14. Оптимизация запросов с select_related и prefetch_related
Задача: Оптимизировать запрос списка заказов с N+1 проблемой.
Промт:
Напиши queryset для получения всех заказов за последний месяц, включая данные о покупателе и все позиции заказа (OrderItem с продуктами). Используй select_related для ForeignKey customer и prefetch_related для обратной связи items__product. Выведи результат в виде списка словарей.
Пример результата:
from django.utils import timezone
from datetime import timedelta
from .models import Order
cutoff = timezone.now() - timedelta(days=30)
orders = Order.objects.filter(
created_at__gte=cutoff
).select_related(
'customer'
).prefetch_related(
'items__product'
)
result = []
for order in orders:
result.append({
'id': order.id,
'customer_email': order.customer.email,
'items': [
{
'product_name': item.product.name,
'quantity': item.quantity
}
for item in order.items.all()
]
})
Пояснение: N+1 проблема — одна из частых причин тормозов. select_related работает для ForeignKey (JOIN), prefetch_related — для ManyToMany и обратных связей (отдельный запрос). Это сокращает количество запросов с 1+N до 3.
15. Кастомный TemplateTag для форматирования дат
Задача: Создать template tag, который выводит дату в формате 'день месяц год' на русском языке.
Промт:
Создай inclusion tag или simple tag под названием 'ru_date', который принимает дату (datetime) и возвращает строку вида '23 июля 2026'. Используй библиотеку pytz или django.utils.timezone для локализации. Зарегистрируй в библиотеке тегов.
Пример результата:
from django import template
from django.utils import timezone
from datetime import datetime
register = template.Library()
MONTHS = {
1: 'января', 2: 'февраля', 3: 'марта', 4: 'апреля',
5: 'мая', 6: 'июня', 7: 'июля', 8: 'августа',
9: 'сентября', 10: 'октября', 11: 'ноября', 12: 'декабря'
}
@register.simple_tag
def ru_date(value):
if isinstance(value, datetime):
local_dt = timezone.localtime(value)
return f'{local_dt.day} {MONTHS[local_dt.month]} {local_dt.year}'
return ''
Пояснение: Кастомные template tags расширяют возможности шаблонизатора. Используйте timezone.localtime для корректного учёта часового пояса. Подключите в шаблоне: {% load ru_date_tags %}.
Заключение
Эти 15 промтов покрывают ключевые аспекты разработки на Django: от моделей и запросов до REST API и админки. Каждый промт — не просто шаблон, а пример, который можно адаптировать под свой проект. Помните: промты экономят время на рутине, но не заменяют понимания архитектуры Django. Регулярно просматривайте официальную документацию (https://docs.djangoproject.com/en/5.0/) и следите за нововведениями в DRF (https://www.django-rest-framework.org/). Начните с малого: возьмите один промт, примените в своём проекте и увидите разницу в скорости разработки. Успешного кодинга!
Комментарии