Создание представления каталога
Чтобы отобразить каталог продуктов, необходимо создать представление для списка всех продуктов или фильтрации продуктов по данной категории. Измените файл views.py приложения shop и добавьте в него следующий код:
from django.shortcuts import render, get_object_or_404
from .models import Category, Product
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = products.filter(category=category)
return render(request,
'shop/product/list.html',
{'category': category,
'categories': categories,
'products': products})
Мы отфильтруем запрос с available=True, чтобы получить только доступные продукты. Мы будем использовать необязательный параметр category_slug, чтобы дополнительно фильтровать продукты по данной категории.
Также требуется представление для извлечения и отображения одного продукта. Добавьте следующий view в файл views.py:
from django.shortcuts import render, get_object_or_404
from .models import Category, Product
def product_list(request, category_slug=None):
category = None
categories = Category.objects.all()
products = Product.objects.filter(available=True)
if category_slug:
category = get_object_or_404(Category, slug=category_slug)
products = products.filter(category=category)
return render(request,
'shop/product/list.html',
{'category': category,
'categories': categories,
'products': products})
def product_detail(request, id, slug):
product = get_object_or_404(Product,
id=id,
slug=slug,
available=True)
return render(request,
'shop/product/detail.html',
{'product': product})
Для получения экземпляра Product в product_detail view рассчитываются параметры id и slug. Этот экземпляр можно получить только с помощью id, поскольку он является уникальным атрибутом. Тем не менее, в URL-адрес можно добавить slug для создания удобных URL-адресов для продуктов.
После построения product list и detail views необходимо определить шаблоны URL-адресов. Создайте новый файл в каталоге приложения shop и назовите его urls.py Добавьте в него следующий код:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.product_list, name='product_list'),
url(r'^(?P<category_slug>[-\w]+)/$',
views.product_list,
name='product_list_by_category'),
url(r'^(?P<id>\d+)/(?P<slug>[-\w]+)/$',
views.product_detail,
name='product_detail'),
]
Это шаблоны URL-адресов для каталога продуктов. Мы определили два различных шаблона URL-адреса для представления product_list: шаблон с именем product_list, который вызывает product_list view без каких-либо параметров; и шаблон с именем product_list_by_category, который предоставляет параметр category_slug в представлении для фильтрации продуктов по данной категории. Мы добавили шаблон для выносного элемента product_detail, который передает в представление параметры id и slug для извлечения конкретного продукта.
Измените файл urls.py проекта myshop:
from django.conf.urls import include, url
from django.contrib import admin
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^', include('shop.urls', namespace='shop')),
]
В основных URL-шаблонах проекта будут включены URL-адреса для приложения shop в пользовательском пространстве имен с именем 'shop'.
Теперь отредактируйте файл models.py приложения shop, импортируйте функцию reverse() и добавьте метод get_absolute_url() в модели Category и Product:
from django.core.urlresolvers import reverse
# ...
class Category(models.Model):
# ...
def get_absolute_url(self):
return reverse('shop:product_list_by_category',
args=[self.slug])
class Product(models.Model):
# ...
def get_absolute_url(self):
return reverse('shop:product_detail',
args=[self.id, self.slug])
Как вы уже знаете, get_absolute_url() — это Конвенция для получения URL-адреса данного объекта. Здесь мы будем использовать шаблоны URL-адресов, которые мы только что определили в файле urls.py.