Закрыть

Для эффективной работы на сайте используются cookie и обработка персональных данных. Пользуясь этим сайтом, вы соглашаетесь с правилами использования сайта. Подробнее

Цитата дня

Vivazzi.ru

Личный сайт Мальцева Артема

Если человек стремится к чему-то всем своим сердцем, он обязательно сумеет добиться того, чего хочет, даже если это кажется невозможным, даже если все окружающие открыто заявляют ему, что это невозможно.

Чак Норрис

5. Каталог

18 октября 2016 г. 22:30

Каталог - это, возможно, та часть, где покупатели нашего интернет-магазина проводят большее время. Часто даже имеет смысл поместить отображение каталога на главную целевую страницу.

В этой документации мы предполагаем, что категории продуктов создаются с использованием специальных помеченных страниц CMS в комбинации с djangoCMS apphook. Это работает отлично для большинства реализаций, но некоторые сайты могут требовать категории, реализация которой не зависит от CMS.

Использование внешнего плагина djangoSHOP для управления категориями является очень осмысленным решением, и мы увидим, отдельные реализации для этого вопроса. Использование такого внешнего плагина для категорий может иметь смысл, если это интернет-магазин требует сотни иерархических уровней и/или эти категории требуют набор атрибутов, которые не доступны в страницах CMS. Если вы собираетесь использовать внешний плагин для категории, пожалуйста, обратитесь к их документации, так как здесь мы используем CMS страницы в качестве категорий.

Хороший аспект djangoSHOP заключается в том, что программисту не нужно писать какие-либо специальные Django представления для того, чтобы отобразить каталог. Вместо этого бизнес-логика продавца проходит через сериализатор, которая в документации назвается как ProductSummarySerializer.

5.1. Представление Catalog List View

В этой документации, представление каталога реализуется в качестве djangoCMS страницы. В зависимости от того, насколько составляющая интернет-магазина является важной частью сайта, мы должны определить подходящее место в структуре страниц и создать новую страницу. Это станет корнем нашего списка каталога.

Во-первых, мы должны создать ProductsListApp.

5.1.1. Создание ProductsListApp

Чтобы получить список продуктовых моделей, Catalog List View требует djangoCMS apphook. Этот ProductsListApp должен быть добавлен в файл, названны cms_apps.py размещён в корневом каталоге торгового приложения.

# myshop/cms_app.py
from cms.app_base import CMSApp
from cms.apphook_pool import apphook_pool

class ProductsListApp(CMSApp):
    name = _("Catalog List")
    urls = ['myshop.urls.products']

apphook_pool.register(ProductsListApp)

как все all apphooks, требуется файл, в котором подключаются url в urlpatterns:

# myshop/urls/products.py

from django.conf.urls import url
from rest_framework.settings import api_settings
from shop.views.catalog import CMSPageProductListView
from myshop.serializers import ProductSummarySerializer

urlpatterns = [
    url(r'^$', CMSPageProductListView.as_view(
        serializer_class=ProductSummarySerializer,
    )),
     # other patterns
]

Здесь ProductSummarySerializer сериализует продуктовые модели в подходящее отображение для рендера внутри CMS страницы, которое сконвертировано в формате JSON. Это позволяет нам переиспользовать такие же Django представления (CMSPageProductListView) всякий раз, когда каталог переключается в режим бесконечной прокрутки, где требуется только краткое описание продукта, которое подгружается как объекты JavaScript.

В случае, если нам нужны дополнительные поля продукта, то нужно просто добавить их к этому классу, используя сериализатором поля из библиотеки Django RESTFramework.

5.1.2. Добавление каталога в CMS

В структуре страниц djangoCMS, создайте новую страницу в подходящем месте на сайте. В качестве названия страницы и слага нам следует использовать что-то, что будет описывать наш каталог продуктов, который будет понятен покупателям и поисковым системам.

Далее, нам нужно изменить расширенные настройки страницы.

Наш шаблон должен содержать заполнитель, так как в нем мы должны поместить плагин, который отобразит наш список продуктов.

В качестве приложения, выберите “Catalog List”, то есть название, которое соответствует нашему ProductsListApp. Этот выбранный apphook мы создали в предыдущей секции.

Затем после сохранения страницы переключитесь в режим "Структура". Добавьте в заполнитель плагин Container, затем в него добавьте Row, а в него Column. Вставьте в Column плагин Catalog List View, который находится в разделе Shop.

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

5.2. Представление Catalog Detail

Страницы карточек товара являются единственными, которые не управляются CMS. Это так, потому что мы часто имеем тысячи продуктов и создать страницу CMS для каждого из них будет своего рода излишеством.

Поэтому используемый шаблон для рендера карточки товара ProductRetrieveView [1] выбирает автоматически по следующему правилам:

  • Найти шаблон, названный <myshop>/catalog/<product-model-name>-detail.html [2][3], иначе
  • Найти шаблон, названный <myshop>/catalog/product-detail.html [2], иначе
  • Использовать шаблон shop/catalog/product-detail.html.

[1] Это представление-класс отвечает за рендер представления карточки товара.

[2](1, 2) <myshop> это название приложения проекта в нижнем регистре.

[3]<product-model-name> это имя класса модели продукта в нижнем регистре.

5.2.1. Использование CMS заполнителей в карточке товара

Если нам требуется функциональность CMS для каждой карточки товара, то добавить её достаточно просто. Добавьте поле djangoCMS Placeholder, названный placeholder в модель класса нашего продукта. А затем добавьте шаблонный тег {% render_placeholder product.placeholder %} в шаблон, который отвечает за карточку товара.

5.2.2. Добавление urls для функционирования карточки товара

ProductsListApp, который мы недавно зарегистрировали в djangoCMS, присоединяет urls, который отвечают за продукт, к общим. Сам файл с urls реализуется путем расширения текущего списка urlpatterns, как описывалось выше:

# myshop/urls/products.py

from django.conf.urls import url
from rest_framework.settings import api_settings
from shop.views.catalog import CMSPageProductListView
from myshop.serializers import ProductSummarySerializer

urlpatterns = [
    url(r'^$', CMSPageProductListView.as_view(
        serializer_class=ProductSummarySerializer,
    )),
     # other patterns
]

Вся бизнес-логика, относящаяся к нашим продуктам, сейчас проводится через наш кастомный класс сериализатора, названный ProductDetailSerializer. Этот класс может иметь доступ к различным атрибутам нашей продуктовой модели и объединить их в сериализуемое представление.

Сериализуемое представление обычно требует все атрибуты из нашей модели, поэтому мы можем просто записать так:

from shop.rest.serializers import ProductDetailSerializerBase

class ProductDetailSerializer(ProductDetailSerializerBase):
    class Meta:
        model = Product
        exclude = ('active',)

В случае, если нам нужны дополнительные сериализованные поля, которые позволяют добавить их к этому классу с помощью полей сериализатора из библиотеки Django RESTFramework.

5.2.2.1. Дополнительные сериализованные поля

Иногда такой сериализованное поле может возвращать HTML фрагмент; это, например, требуется для изображений товара (<img src="..." />), для которых должны создаваться миниатюры с помощью шаблонного тега из библиотеки easythumbnail. Для этих случаев добавьте поле типа foo = SerializerMethodField() с соответствующим методом get_foo() в наш класс сериализатора. Это позволит методу напрямую передавать данный продукт во встроенный рендер:

class ProductDetailSerializer(ProductDetailSerializerBase):
    # other attributes

    def get_foo(self, product):
        return self.render_html(product, 'foo')

Этот метод HTML рендера находит шаблон по следующим правилам:

  • Найти шаблон, названный <myshop>/product/catalog-<product-model-name>-<second-argument>.html [4] [5] [6], иначе
  • Найти шаблон, названный <myshop>/product/catalog-product-<second-argument>.html [4] [6], иначе
  • Использовать шаблон shop/product/catalog-product-<second-argument>.html [6].

[4](1, 2) <myshop> - это название приложения проекта в нижнем регистре.

[5]<product-model-name> - это имя класса проекта в нижнем регистре.

[6](1, 2, 3) <field-name> - это имя атрибута объявленного поля в нижнем регистре.

5.2.3. Эмуляция категорий

Поскольку мы хотим использовать CMS страницы для эмуляции категорий, модель продукта должна объявлять связи между CMS страницами и собой. Это обычно достигается засчёт добавления many-to-many поля, названного cms_pages в нашу модель продукта.

Так как мы работаем с отложенными моделями, мы не можем использовать таблицу отображения, которую обычно автоматически генерирует Django фреймворк для many-to-many поля.

class ProductPage(BaseProductPage):
    """Materialize many-to-many relation with CMS pages"""

class Product(BaseProduct):
    # other model fields
    cms_pages = models.ManyToManyField('cms.Page',
        through=ProductPage)

    objects = ProductManager()

В этом примере класс ProductPage отвечает за хранение информации отображения между нашими Product объектами и CMS страницами.

5.2.3.1. Интеграция в админке

Чтобы упростить объявление админ-бэкенда, используемого для управления нашей модели продукта, djangoSHOP поставляется со специальным миксин-классом, который должен быть добавлен к админ-классу продукта:

@admin.register(Product)
class ProductAdmin(CMSPageAsCategoryMixin, admin.ModelAdmin):
    fields = ('product_name', 'slug', 'product_code',
        'unit_price', 'active', 'description',)
    # other admin declarations

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

Если мы используем метод render_html() для рендера HTML сниппетов, то они будут закешированы при условии, что кеширование настроено и доступно для этого проекта. Кеширование этих сниппетов настоятельно рекомендуется и даёт заметный прирост производительности, особенно при рендере представления списка каталога.

Так как мы вынуждены были бы ждать до тех пор, пока у них истечёт срок действия

Так как мы должны ждать, пока у них не истечёт срок действия естественным путем, djangoSHOP предлагает миксин-класс, который добавляется к админ-классу для того, чтобы сбросить срок действия HTML сниппетов продукта всякий раз, когда продукт сохранен в бэкенде. Просто добавьте shop.admin.product.InvalidateProductCacheMixin к классу ProductAdmin, описанным выше.

Замечание

Обычно ключи обрабатываются во многих системах кэширования, то InvalidateProductCacheMixin имеет смысл добавлять только при использовании redis_cache бэкэнда.

Оцените статью

5 из 5 (всего 2 оценки)

Поля, отмеченные звёздочкой ( * ) , являются обязательными.

Спасибо за ваш отзыв!

Автор перевода

Права на использование данной статьи, расположенной на настоящей странице http://vivazzi.ru/django-shop/catalog/:

Разрешается копировать статью с указанием её автора и ссылки на оригинал без использования параметра rel="nofollow" в теге <a>. Использование:

Автор статьи: Мальцев Артём
Ссылка на статью: <a href="http://vivazzi.ru/django-shop/catalog/">http://vivazzi.ru/django-shop/catalog/</a>

Подробнее: Правила использования сайта

Вам нужно саморазвиваться или вы хотите зарабатывать деньги?

Или вы ищите хорошие IT сервисы или книги? Сохраните свое время и взгляните на мою подборку рекомендаций, которыми постоянно пользуюсь.
Посмотреть рекомендации

Комментариев: 0

Вы можете оставить комментарий как незарегистрированный пользователь. Но, зарегистрировавшись, вы сможете получать оповещения об ответах, а также иметь доступ к своему личному аккаунту для просмотра своих комментариев.

Чтобы оставить комментарий от своего имени войдите или зарегистрируйтесь обычным способом или через социальные сети:

Отправить

На данный момент нет специального поиска, поэтому я предлагаю воспользоваться обычной поисковой системой, например, Google, добавив "vivazzi" после своего запроса.

Попробуйте