Skip to content

Commit

Permalink
#550 Fork TaggedCategoryContext class
Browse files Browse the repository at this point in the history
  • Loading branch information
duker33 committed Sep 1, 2018
1 parent 8d41122 commit 6e38729
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 69 deletions.
128 changes: 94 additions & 34 deletions shopelectro/context.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@
from pages.models import ModelPage, Page


class SortingOption:
def __init__(self, index=0):
options = settings.CATEGORY_SORTING_OPTIONS[index]
self.label = options['label']
self.field = options['field']
self.direction = options['direction']

@property
def directed_field(self):
return self.direction + self.field


@lru_cache(maxsize=64)
def merge_products_context(products):
images = Image.objects.get_main_images_by_pages(
Expand All @@ -52,53 +64,66 @@ class ObjectsComposition:

super = object()

# TODO - resolve objects good piping
def __or__(self, other):
self.super = other
return self


class AbstractContext(ObjectsComposition):

# TODO - raise not implemented here
# @property
# def request(self):
# raise NotImplemented()
def __init__(
self,
# TODO slug maybe part of url_kwargs
slug='',
url_kwargs: typing.Dict[str, str]=None,
request: http.HttpRequest=None
):
"""
:param url_kwargs: Came from `urls` module.
:param request: Came from `urls` module
"""
self.slug_ = slug
self.url_kwargs_ = url_kwargs or {}
self.request_ = request

@property
def slug(self) -> str:
return self.slug_ or self.super.slug

@property
def url_kwargs(self) -> typing.Dict[str, str]:
return self.url_kwargs_ or self.super.url_kwargs

@property
def request(self) -> http.HttpRequest:
return self.request_ or self.super.request

# @property
# def page(self) -> Page:
# """Page from DB, that should be selected"""
# raise NotImplemented()
@property
@lru_cache(maxsize=1)
def page(self):
return ModelPage.objects.get(slug=self.slug)

def get_context_data(self, **kwargs) -> dict:
raise NotImplemented()
def get_context_data(self) -> typing.Dict[str, typing.Any]:
raise NotImplementedError


class ProductsListContext(AbstractContext):
@property
def products(self) -> QuerySet:
raise NotImplemented()
raise NotImplementedError


# TODO - fork PageContext
class CategoryContext(ProductsListContext):

# TODO - annotate it
def __init__(self, slug, request):
self.slug = slug
self.request = request

@property
@lru_cache(maxsize=1)
def page(self):
return ModelPage.objects.get(slug=self.slug)

@property
@lru_cache(maxsize=1)
def products(self) -> QuerySet:
return models.Product.actives.get_category_descendants(
self.page.model
)

def get_context_data(self, **kwargs):
def get_context_data(self):
"""Add sorting options and view_types in context."""
# TODO take from dataclass or smth
view_type = self.request.session.get('view_type', 'tile')
Expand All @@ -117,17 +142,52 @@ def get_context_data(self, **kwargs):
}


# class TaggedCategoryContext:
# def products(tags):
# return self.super.products().and_aother_fetch(catalog)
#
# def get_context_data():
# return {
# **self.super.get_context_data(),
# ... # and something simple only about tags
# }
#
#
class TaggedCategoryContext(ProductsListContext):

def get_sorting_index(self):
return int(self.url_kwargs.get('sorting', 0))

# TODO - test if it's cached
def get_tags(self) -> typing.Optional[models.TagQuerySet]:

@lru_cache(maxsize=64)
def get_tags(request_tags_: str):
slugs = models.Tag.parse_url_tags(request_tags_)
return models.Tag.objects.filter(slug__in=slugs)

request_tags = self.url_kwargs.get('tags')
if not request_tags:
return None
return get_tags(request_tags)

@property
@lru_cache(maxsize=1)
def products(self):
products = self.super.products
sorting_option = SortingOption(index=self.get_sorting_index())
tags = self.get_tags()
if tags:
products = (
products
.filter(tags__in=tags)
# Use distinct because filtering by QuerySet tags,
# that related with products by many-to-many relation.
# TODO - try to rm this sorting staff
.distinct(sorting_option.field)
)
return products

def get_context_data(self):
context = self.super.get_context_data()
tags = self.get_tags()
return {
**context,
'tags': tags,
# TODO write comment about skip_canonical
'skip_canonical': bool(tags),
}


# class PaginatedCatalogContext:
# ...
#
Expand Down
41 changes: 6 additions & 35 deletions shopelectro/views/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -189,19 +189,18 @@ def get_products(self) -> QuerySet:

def get_context_data(self, **kwargs):
"""Add sorting options and view_types in context."""
context_ = context.CategoryContext(self.object.slug, self.request)
context_ = context.TaggedCategoryContext() | context.CategoryContext(
self.object.slug, kwargs, self.request
)
return {
**super().get_context_data(**kwargs),
**context_.get_context_data(),
}


class TaggedCategoryPage(CategoryPage):

def get_sorting_index(self):
return int(self.kwargs.get('sorting', 0))
class DBContextCategoryPage(CategoryPage):
"""Process db page data as db context."""

# TODO - test if it's cached
def get_tags(self) -> typing.Optional[models.TagQuerySet]:

@lru_cache(maxsize=64)
Expand All @@ -214,34 +213,6 @@ def get_tags(request_tags_: str):
return None
return get_tags(request_tags)

def get_products(self):
products = super().get_products()
sorting_option = SortingOption(index=self.get_sorting_index())
tags = self.get_tags()
if tags:
products = (
products
.filter(tags__in=tags)
# Use distinct because filtering by QuerySet tags,
# that related with products by many-to-many relation.
.distinct(sorting_option.field)
)
return products

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
tags = self.get_tags()
return {
**context,
'tags': tags,
# TODO write comment about skip_canonical
'skip_canonical': bool(tags),
}


class DBContextCategoryPage(TaggedCategoryPage):
"""Process db page data as db context."""

def get_object(self, queryset=None):
page = super().get_object(queryset)

Expand All @@ -252,7 +223,7 @@ def template_context(page, tag_titles, tags):
'tags': tags,
}

tags = super().get_tags()
tags = self.get_tags()
if tags:
# TODO - move to QuerySet
tag_titles = models.serialize_tags_to_title(tags)
Expand Down

0 comments on commit 6e38729

Please sign in to comment.