IT-журнал

Корзина покупок на Django: от сессий до базы данных

Узнайте, как реализовать функционал корзины в интернет-магазине на Django с использованием сессий и моделей данных.

Обновлено 20.09.2026

⏱ 2 мин чтения · 👁 прочитали 3

Реализация корзины покупок — это базовый, но критически важный этап разработки любого e-commerce проекта. Главный архитектурный вопрос здесь заключается в выборе места хранения данных: в сессии пользователя (для неавторизованных гостей) или в базе данных (для постоянного хранения и синхронизации между устройствами).

В этой статье мы разберем гибридный подход, который позволит пользователям добавлять товары в корзину без регистрации, а после входа в систему — сохранять их выбор.

Архитектура хранения данных

Для реализации корзины мы будем использовать django.contrib.sessions. Это позволит нам хранить ID товаров и их количество в JSON-подобной структуре в сессии пользователя.

Почему сессии?

  1. Скорость: Не нужно делать запрос к БД при каждом обновлении страницы.
  2. UX: Пользователь может начать покупки, не проходя через форму регистрации.
  3. Снижение нагрузки: БД не забивается временными данными «брошенных корзин».

Пошаговая реализация

1. Создание класса Cart

Вместо того чтобы писать логику прямо во views, создадим отдельный класс-менеджер для работы с корзиной. Создайте файл cart.py в вашем приложении.

from decimal import Decimal
from django.conf import settings

class Cart:
    def __init__(self, request):
        self.session = request.session
        cart = self.session.get('session_cart')
        if not cart:
            cart = self.session['session_cart'] = {}
        self.cart = cart

    def add(self, product, quantity=1, override_quantity=False):
        product_id = str(product.id)
        if product_id not in self.cart:
            self.cart[product_id] = {'quantity': 0, 'price': str(product.price)}

        if override_quantity:
            self.cart[product_id]['quantity'] = quantity
        else:
            self.cart[product_id]['quantity'] += quantity

        self.save()

    def save(self):
        self.session.modified = True

    def remove(self, product):
        product_id = str(product.id)
        if product_id in self.cart:
            del self.cart[product_id]
            self.save()

    def __iter__(self):
        # Здесь логика получения объектов товаров из БД на основе ID в сессии
        pass

    def get_total_price(self):
        return sum(Decimal(item['price']) * item['quantity'] for item in self.cart.values())

    def clear(self):
        del self.session['session_cart']
        self.save()

2. Создание View для управления корзиной

Теперь создадим обработчики для добавления и удаления товаров.

from django.shortcuts import redirect, get_object_or_404, render
from .models import Product
from .cart import Cart

def cart_add(request, product_id):
    cart = Cart(request)
    product = get_object_or_404(Product, id=product_id)
    cart.add(product=product, quantity=1)
    return redirect('cart_detail')

def cart_remove(request, product_id):
    cart = Cart(request)
    product = get_object_or_404(Product, id=product_id)
    cart.remove(product)
    return redirect('cart_detail')

def cart_detail(request):
    cart = Cart(request)
    # Дополнительная логика для получения списка объектов товаров
    return render(request, 'cart/detail.html', {'cart': cart})

3. Настройка URL-путей

Добавьте соответствующие пути в urls.py:

from django.urls import path
from . import views

urlpatterns = [
    path('cart/add/<int:product_id>/', views.cart_add, name='cart_add'),
    path('cart/remove/<int:product_id>/', views.cart_remove, name='cart_remove'),
    path('cart/', views.cart_detail, name='cart_detail'),
]

Оптимизация и безопасность

Проблема N+1

При выводе корзины в шаблоне часто возникает проблема N+1 запросов к базе данных (один запрос на корзину + по одному запросу на каждый товар). Чтобы этого избежать, используйте метод __iter__ в классе Cart с применением .filter(id__in=self.cart.keys()).select_related(...).

Валидация остатков

Перед методом self.save() в классе Cart рекомендуется добавить проверку наличия товара на складе (Product.stock), чтобы пользователь не мог добавить в корзину больше единиц, чем доступно в реальности.

Заключение

Использование сессий для корзины в Django — это сбалансированное решение, которое обеспечивает высокую скорость работы и удобство для пользователя. Для масштабирования проекта (например, при переходе на Redis для хранения сессий) данный подход останется актуальным, так как логика инкапсулирована в отдельном классе.

Следующим шагом в развитии системы может стать создание модели Order и OrderItem, куда данные из сессионной корзины будут переноситься в момент оформления заказа.