Skip to content

Commit

Permalink
#550 Merge fixes after hell
Browse files Browse the repository at this point in the history
# Conflicts:
#	shopelectro/models.py
#	shopelectro/views/catalog.py
  • Loading branch information
duker33 committed Sep 7, 2018
1 parent 9f68373 commit 89d0c15
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 41 deletions.
49 changes: 48 additions & 1 deletion shopelectro/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,42 @@ def directed_field(self):
return self.direction + self.field


# @todo #539:60m Move PaginatorLinks to refarm-site.
class PaginatorLinks:

def __init__(self, number, path, paginated: Paginator):
self.paginated = paginated
self.number = number
self.path = path

self.index = number - 1
self.neighbor_bounds = settings.PAGINATION_NEIGHBORS // 2
self.neighbor_range = list(self.paginated.page_range)

def page(self):
try:
return self.paginated.page(self.number)
except InvalidPage:
raise http.Http404('Page does not exist')

def showed_number(self):
return self.index * self.paginated.per_page + self.page().object_list.count()

def _url(self, number):
self.paginated.validate_number(number)
return self.path if number == 1 else f'{self.path}?page={number}'

def prev_numbers(self):
return self.neighbor_range[:self.index][-self.neighbor_bounds:]

def next_numbers(self):
return self.neighbor_range[self.index + 1:][:self.neighbor_bounds]

def number_url_map(self):
numbers = self.prev_numbers() + self.next_numbers()
return {number: self._url(number) for number in numbers}


# @todo #550:30m Split to ProductImagesContext and ProductBrandContext
@lru_cache(maxsize=64)
def merge_products_context(products: QuerySet):
Expand Down Expand Up @@ -194,7 +230,10 @@ def get_tags(request_tags_: str):
request_tags = self.url_kwargs.get('tags')
if not request_tags:
return None
return get_tags(request_tags)
tags = get_tags(request_tags)
if not tags:
raise http.Http404('No such tag.')
return tags

@property
def products(self):
Expand Down Expand Up @@ -317,11 +356,19 @@ def get_context_data(self):
if not products:
raise http.Http404('Page without products does not exist.')

paginated = PaginatorLinks(
page_number,
self.request.path,
Paginator(self.products, products_on_page)
)
paginated_page = paginated.page()

return {
**context,
'products_data': merge_products_context(products),
'total_products': total_products,
'products_count': (page_number - 1) * products_on_page + products.count(),
'paginated': paginated,
'paginated_page': paginated_page,
'sorting_options': settings.CATEGORY_SORTING_OPTIONS.values(),
'limits': settings.CATEGORY_STEP_MULTIPLIERS,
Expand Down
32 changes: 8 additions & 24 deletions shopelectro/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import string
from itertools import chain, groupby
from operator import attrgetter
from typing import Dict, List, Optional, Tuple
import typing
from uuid import uuid4

from django.conf import settings
Expand All @@ -19,6 +19,7 @@
CategoryManager,
ProductActiveManager,
ProductManager,
TagGroup as caTagGroup,
)
from ecommerce.models import Order as ecOrder
from pages.models import CustomPage, ModelPage, Page, SyncPageMixin, PageManager
Expand Down Expand Up @@ -119,18 +120,8 @@ def feedback(self):
def get_params(self):
return Tag.objects.filter_by_products([self]).get_group_tags_pairs()

# @todo #388:30m Move Product.get_siblings method to refarm-site
# And reuse it on STB.
def get_siblings(self, offset):
return (
self.__class__.actives
.filter(category=self.category)
.prefetch_related('category')
.select_related('page')[:offset]
)

def get_brand_name(self) -> str:
brand: Optional['Tag'] = Tag.objects.get_brands([self]).get(self)
brand: typing.Optional['Tag'] = Tag.objects.get_brands([self]).get(self)
return brand.name if brand else ''


Expand Down Expand Up @@ -210,22 +201,17 @@ class Meta(ModelPage.Meta): # Ignore PycodestyleBear (E303)
objects = ModelPage.create_model_page_managers(Product)


class TagGroup(models.Model):
class TagGroup(caTagGroup):
pass

uuid = models.UUIDField(default=uuid4, editable=False) # Ignore CPDBear
name = models.CharField(
max_length=100, db_index=True, verbose_name=_('name'))
position = models.PositiveSmallIntegerField(
default=0, blank=True, db_index=True, verbose_name=_('position'),
)

def __str__(self):
return self.name


class TagQuerySet(models.QuerySet):

def filter_by_products(self, products: List[Product]):
def filter_by_products(self, products: typing.List[Product]):
ordering = settings.TAGS_ORDER
distinct = [order.lstrip('-') for order in ordering]

Expand All @@ -236,14 +222,14 @@ def filter_by_products(self, products: List[Product]):
.distinct(*distinct, 'id')
)

def get_group_tags_pairs(self) -> List[Tuple[TagGroup, List['Tag']]]:
def get_group_tags_pairs(self) -> typing.List[typing.Tuple[TagGroup, typing.List['Tag']]]:
grouped_tags = groupby(self.prefetch_related('group'), key=attrgetter('group'))
return [
(group, list(tags_))
for group, tags_ in grouped_tags
]

def get_brands(self, products: List[Product]) -> Dict[Product, 'Tag']:
def get_brands(self, products: typing.List[Product]) -> typing.Dict[Product, 'Tag']:
brand_tags = (
self.filter(group__name=settings.BRAND_TAG_GROUP_NAME)
.prefetch_related('products')
Expand Down Expand Up @@ -336,8 +322,6 @@ class Tag(models.Model):
TagGroup, on_delete=models.CASCADE, null=True, related_name='tags',
)

def __str__(self):
return self.name

def save(self, *args, **kwargs):
if not self.slug:
Expand Down
24 changes: 8 additions & 16 deletions shopelectro/views/catalog.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import typing
from functools import lru_cache, partial
from functools import lru_cache

from django import http
from django.db.models import QuerySet
from django.conf import settings
from django.core.paginator import Paginator, InvalidPage
from django.shortcuts import render, get_object_or_404
Expand All @@ -26,13 +25,6 @@ def get_products_count(request):
return PRODUCTS_ON_PAGE_MOB if mobile_view else PRODUCTS_ON_PAGE_PC


def get_paginated_page_or_404(objects, per_page, page_number):
try:
return Paginator(objects, per_page).page(page_number)
except InvalidPage:
raise http.Http404('Page does not exist')


class SortingOption:
def __init__(self, index=0):
options = settings.CATEGORY_SORTING_OPTIONS[index]
Expand Down Expand Up @@ -180,11 +172,6 @@ def merge_products_context(products):
@set_csrf_cookie
class CategoryPage(catalog.CategoryPage):

def get_products(self) -> QuerySet:
return models.Product.actives.get_category_descendants(
self.object.model
)

def get_context_data(self, **kwargs):
"""Add sorting options and view_types in context."""
context_ = (
Expand All @@ -200,7 +187,6 @@ def get_context_data(self, **kwargs):
}


# @todo #550:60m Make `catalog.views.load_more` one of the context classes
def load_more(request, category_slug, offset=0, limit=0, sorting=0, tags=None):
"""
Load more products of a given category.
Expand Down Expand Up @@ -246,12 +232,18 @@ def load_more(request, category_slug, offset=0, limit=0, sorting=0, tags=None):
.distinct(sorting_option.field)
)

paginated_page = get_paginated_page_or_404(all_products, products_on_page, page_number)
paginated = context.PaginatorLinks(
page_number,
request.path,
Paginator(all_products, products_on_page)
)
paginated_page = paginated.page()
products = paginated_page.object_list
view = request.session.get('view_type', 'tile')

return render(request, 'catalog/category_products.html', {
'products_data': merge_products_context(products),
'paginated': paginated,
'paginated_page': paginated_page,
'view_type': view,
'prods': products_on_page,
Expand Down

0 comments on commit 89d0c15

Please sign in to comment.