Дикий Григорий

Full-stack веб-разработчик

Интернет-магазин на Django. Корзина пользователя. Часть 5

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

def CartDetail(request):
    cart = Cart(request)
    for item in cart:
        item['update_quantity_form'] = CartAddProductForm(
                                        initial={
                                            'quantity': item['quantity'],
                                            'update': True
                                        })
    return render(request, 'cart/detail.html', {'cart': cart})

Мы создали экземпляр класса CartAddProductForm для каждого товара нашей корзины, что позволит в изменять количество товаров на странице корзины товаров. Также мы выставили у поля update значение True. Этим самым старое значение будет перезаписано новым. Теперь давайте изменим шаблон cart/detail.html таким образом, чтобы он выводил форму. Найдем в шаблоне {{ item.quantity }} и вместо него вставим следующее:

<form action="{% url "cart:CartAdd" product.id %}" method="post" class="add">
    {{ item.update_quantity_form.quantity }}
    {{ item.update_quantity_form.update }}
    {% csrf_token %}
    <input type="submit" value="Обновить">
</form>

В итоге страница корзины пользователя будет выглядеть так:

Контекстный процессор

Бывают случаи когда нужно динамически отобразить информацию на страницах сайта. И эта информация часто повторяется. В нашем случае это надпись "Ваша корзина пуста". Мы могла бы передавать cart во все шаблоны через вьюхи, но если сайт разрастается, то такой код сложно поддерживать. Эту проблему поможет решить контекстный процессор. По умолчанию при создании проложения в Django создаются прописываются дефолтные контекстные процессоры в файле settings.py в переменной TEMPLATES:

'context_processors': [
    'django.template.context_processors.debug',
    'django.template.context_processors.request',
    'django.contrib.auth.context_processors.auth',
    'django.contrib.messages.context_processors.messages',
]
  • django.template.context_processors.debug - помещает отладочную информацию в шаблон. Если он подключен, то вы сможете использовать следующие переменные в шаблоне: debug - булева переменная, sql_queries - список словарей с SQL запросами.
  • django.core.context_processors.request - содержит переменную request, которая отвечает за запросы к серверу.
  • django.core.context_processors.auth - процессор нужный для работы с авторизацией пользователя. В шаблоне можно использовать:
    • user - переменная предоставляющая авторизированного пользователя. Экземпляр класса django.contrib.auth.models.User. Когда пользователь не авторизирован, то user будет экземпляром AnonymousUser.
    • perms - права текущего пользователя
    • messages - сообщения текущего пользователя

Также по умолчанию Django включает django.template.context_processors.csrf, для того, чтобы не позволить злоумышленнику совершить кроссдоменную атаку и выполнять действия от имени другого пользователя.

Создадим для нашего онлайн-магазина контекстный процессор, для этого в директории cart создайте файл с названием context_processors.py со следующим содержанием:

from .cart import Cart


def cart(request):
    return {'cart': Cart(request)}
Как видно контекстный процессор - есть функция, которая принимает в качестве параметра request и возвращает словарь объектов доступных в шаблоне. Подключим этот файл в settings.py в переменной TEMPLATES:

....
'django.contrib.messages.context_processors.messages',
'cart.context_processors.cart'
Теперь контекстный процессор будет всегда выполняться при рендеринге страницы и переменная cart будет постоянно обновятся. В этой переменной будут хранится все необходимые нам данные, так как мы ее инициализируем при помощи request, который уже хранит в себе информацию о сессиях. Теперь давайте изменим шаблон shop/base.html из директории shop:

<div class="cart">
    {% with total_items=cart|length %}
        {% if cart|length > 0 %}
            Ваша корзина:
            <a href="{% url "cart:CartDetail" %}">
                {{ total_items }} тов. {{ cart.get_total_price }} руб.
            </a>
         {% else %}
              Корзина пустая
        {% endif %}
    {% endwith %}
</div>

В итоге мы у нас получится страница:


Репозиторий проекта: github