Разработка бэкенда сайта на Python (Django)

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

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

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Разработка бэкенда сайта на Python (Django)
Средняя
от 1 недели до 3 месяцев
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Разработка бэкенда сайта на Python (Django)

Django — «batteries included» в буквальном смысле. ORM, миграции, admin-панель, аутентификация, формы, кеширование, i18n — всё это из коробки, без выбора библиотек и интеграции компонентов. Это делает Django самым быстрым способом запустить полноценный бэкенд, если не нужна экзотика.

Типовая область применения: корпоративные сайты, CMS, порталы, API для SPA и мобильных приложений, системы с богатой бизнес-логикой и ролевой моделью.

Структура проекта

Django-проект состоит из проекта (project) и приложений (apps). Хорошая практика — делать apps небольшими и функционально изолированными:

myproject/
  manage.py
  config/
    settings/
      base.py
      development.py
      production.py
    urls.py
    wsgi.py
    asgi.py
  apps/
    users/
      models.py
      views.py
      serializers.py  # для DRF
      urls.py
      admin.py
      services.py      # бизнес-логика отдельно от views
      tests/
        test_models.py
        test_views.py
    products/
    orders/
  requirements/
    base.txt
    development.txt
    production.txt

Settings разделяем по окружениям и никогда не коммитим секреты в репозиторий:

# config/settings/base.py
from pathlib import Path
import environ

env = environ.Env()
BASE_DIR = Path(__file__).resolve().parent.parent.parent

SECRET_KEY = env('DJANGO_SECRET_KEY')
DATABASES = {
    'default': env.db('DATABASE_URL', default='postgres://localhost/mydb')
}
CACHES = {
    'default': {
        'BACKEND': 'django_redis.cache.RedisCache',
        'LOCATION': env('REDIS_URL', default='redis://localhost:6379/0'),
        'OPTIONS': {'CLIENT_CLASS': 'django_redis.client.DefaultClient'}
    }
}

Модели и ORM

Сильная сторона Django — выразительный ORM с поддержкой сложных запросов:

from django.db import models
from django.contrib.postgres.fields import ArrayField
from django.contrib.postgres.indexes import GinIndex

class Product(models.Model):
    name = models.CharField(max_length=255)
    slug = models.SlugField(unique=True)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    category = models.ForeignKey('Category', on_delete=models.SET_NULL, null=True)
    attributes = models.JSONField(default=dict)
    tags = ArrayField(models.CharField(max_length=50), default=list)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        indexes = [
            models.Index(fields=['slug']),
            models.Index(fields=['category', 'is_active']),
            GinIndex(fields=['attributes']),  # для поиска по JSONB
        ]
        ordering = ['-created_at']

    def __str__(self):
        return self.name

Сложные запросы через annotate, aggregate, prefetch_related:

from django.db.models import Count, Avg, Q, Prefetch

# Получить категории с количеством активных продуктов и средней ценой
categories = Category.objects.annotate(
    products_count=Count('product', filter=Q(product__is_active=True)),
    avg_price=Avg('product__price', filter=Q(product__is_active=True))
).filter(products_count__gt=0).order_by('-products_count')

# N+1 проблема решается через prefetch_related
orders = Order.objects.prefetch_related(
    Prefetch('items', queryset=OrderItem.objects.select_related('product'))
).select_related('user').filter(status='processing')

Django REST Framework

DRF — стандарт для API на Django. Сериализаторы, ViewSets, пагинация:

from rest_framework import serializers, viewsets, permissions, filters
from rest_framework.decorators import action
from rest_framework.response import Response
from django_filters.rest_framework import DjangoFilterBackend

class ProductSerializer(serializers.ModelSerializer):
    category_name = serializers.CharField(source='category.name', read_only=True)

    class Meta:
        model = Product
        fields = ['id', 'name', 'slug', 'price', 'category', 'category_name', 'attributes']
        read_only_fields = ['slug']

    def validate_price(self, value):
        if value <= 0:
            raise serializers.ValidationError('Цена должна быть положительной')
        return value

class ProductViewSet(viewsets.ModelViewSet):
    queryset = Product.objects.select_related('category').filter(is_active=True)
    serializer_class = ProductSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    filter_backends = [DjangoFilterBackend, filters.SearchFilter, filters.OrderingFilter]
    filterset_fields = ['category', 'is_active']
    search_fields = ['name', 'description']
    ordering_fields = ['price', 'created_at']
    ordering = ['-created_at']

    @action(detail=True, methods=['post'], permission_classes=[permissions.IsAuthenticated])
    def favorite(self, request, pk=None):
        product = self.get_object()
        request.user.favorites.add(product)
        return Response({'status': 'added'})

Аутентификация

JWT через djangorestframework-simplejwt:

# config/urls.py
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView

urlpatterns = [
    path('api/auth/login/', TokenObtainPairView.as_view()),
    path('api/auth/refresh/', TokenRefreshView.as_view()),
]

Кастомный payload JWT:

from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

class CustomTokenSerializer(TokenObtainPairSerializer):
    @classmethod
    def get_token(cls, user):
        token = super().get_token(user)
        token['email'] = user.email
        token['role'] = user.role
        return token

Celery для фоновых задач

# tasks.py
from celery import shared_task
from django.core.mail import send_mail

@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def send_order_confirmation(self, order_id: int) -> None:
    try:
        order = Order.objects.select_related('user').get(id=order_id)
        send_mail(
            subject=f'Заказ #{order.id} подтверждён',
            message=render_email_template('order_confirmation', order),
            from_email=settings.DEFAULT_FROM_EMAIL,
            recipient_list=[order.user.email]
        )
    except Order.DoesNotExist:
        # не повторять — объект не найден
        return
    except Exception as exc:
        raise self.retry(exc=exc)

Кеширование

from django.core.cache import cache
from django.views.decorators.cache import cache_page
from functools import wraps

# Низкоуровневое кеширование
def get_popular_products():
    cache_key = 'popular_products'
    result = cache.get(cache_key)
    if result is None:
        result = list(Product.objects.filter(is_active=True).order_by('-views')[:10])
        cache.set(cache_key, result, timeout=300)
    return result

# Инвалидация по тегам через django-cache-memoize
from cache_memoize import cache_memoize

@cache_memoize(300, extra_verbose_cache_key=True)
def get_category_products(category_id: int, page: int = 1):
    # ...

Admin-панель

Встроенная admin-панель Django экономит недели работы:

@admin.register(Product)
class ProductAdmin(admin.ModelAdmin):
    list_display = ['name', 'price', 'category', 'is_active', 'created_at']
    list_filter = ['category', 'is_active', 'created_at']
    search_fields = ['name', 'slug']
    list_editable = ['is_active', 'price']
    prepopulated_fields = {'slug': ('name',)}
    readonly_fields = ['created_at', 'updated_at']

    def get_queryset(self, request):
        return super().get_queryset(request).select_related('category')

Сроки разработки

  • Настройка проекта, БД, auth — 3–5 дней
  • Модели + миграции + admin — 1 неделя
  • API на DRF — 1–3 недели в зависимости от сложности
  • Celery + Redis + очереди — 3–5 дней
  • Интеграции (платёжки, email, сторонние API) — 1–2 недели
  • Тесты (pytest-django) — 1 неделя

Полноценный бэкенд для корпоративного сайта или портала: 5–10 недель. Django окупает себя встроенной admin-панелью — часто клиент управляет контентом через неё без отдельного CMS.