Skip to content
This repository has been archived by the owner on Feb 23, 2020. It is now read-only.

Commit

Permalink
#744 Use Option for pdf price list (#748)
Browse files Browse the repository at this point in the history
* Ignore sublime settings

* Decompose Filtered class

* Remove Product in favor Option for pdf view

* Create todo to continue

* Linter fixes

* Review fixes
  • Loading branch information
ArtemijRodionov committed Jul 12, 2019
1 parent 3b30baa commit 3ca7da2
Show file tree
Hide file tree
Showing 8 changed files with 126 additions and 41 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ package-lock.json
report.xml
database
*.orig
*.sublime-project
*.sublime-workspace
1 change: 1 addition & 0 deletions stroyprombeton/context/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .catalog import *
from . import options, tags
19 changes: 7 additions & 12 deletions stroyprombeton/context/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@
from catalog import context, typing
from images.models import Image
from pages import context as pages_context
from stroyprombeton import models as stb_models, request_data
from stroyprombeton.context import options
from stroyprombeton import models as stb_models, context as stb_context, request_data


class TagsByOptions(context.Tags):
Expand Down Expand Up @@ -75,13 +74,9 @@ def category(self):
id=self.request_data.id
)

@property
def tags(self) -> context.Tags:
return context.Tags(stb_models.Tag.objects.all())

def context(self) -> typing.ContextDict:
tags = FilteredTags(stb_models.Tag.objects.all(), self.request_data)
options_ = options.Filtered(self.category, tags.qs(), self.request_data)
options_ = stb_context.options.Filtered(self.category, tags.qs())

if not options_.qs():
raise http.Http404('<h1>В категории нет изделий</h1')
Expand All @@ -100,7 +95,7 @@ def context(self) -> typing.ContextDict:
sliced_options.products, Image.objects.all()
)
grouped_tags = context.tags.GroupedTags(
tags=TagsByOptions(self.tags, options_.qs())
tags=TagsByOptions(stb_context.tags.All(), options_.qs())
)
page = Page(self.page, tags)
category = CategoryContext(self.request_data)
Expand Down Expand Up @@ -162,12 +157,12 @@ def __init__(self, request_data_: request_data.FetchProducts):
def context(self) -> typing.ContextDict:
category = CategoryContext(self.request_data)
tags = FilteredTags(stb_models.Tag.objects.all(), self.request_data)
options_ = options.Sliced(
options_ = stb_context.options.Sliced(
request_data_=self.request_data,
options=options.Searched(
options=stb_context.options.Searched(
request_data_=self.request_data,
options=options.Filtered(
category.object(), tags.qs(), self.request_data
options=stb_context.options.Filtered(
category.object(), tags.qs(),
)
)
)
Expand Down
66 changes: 56 additions & 10 deletions stroyprombeton/context/options.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,28 +49,74 @@ def context(self) -> typing.ContextDict:
}


class Filtered(Options):
class All(Options):

def __init__(self, qs: stb_models.OptionQuerySet = None):
self._qs = qs or stb_models.Option.objects.all()

def qs(self) -> stb_models.OptionQuerySet:
return (
self._qs
.bind_fields()
.active()
.order_by(*settings.OPTIONS_ORDERING)
)


class CategoryFiltered(Options):

def __init__(
self,
category: stb_models.Category,
tags: stb_models.TagQuerySet,
request_data_: request_data.Category
options: Options,
category: stb_models.Category
):
self.options = options
self.category = category
self.tags = tags
self.request_data = request_data_

def qs(self) -> stb_models.OptionQuerySet:
return (
stb_models.Option.objects
.bind_fields()
.active()
self.options
.qs()
.filter_descendants(self.category)
)


class TagsFiltered(Options):
def __init__(
self,
options: Options,
tags: stb_models.TagQuerySet,
):
self.options = options
self.tags = tags

def qs(self) -> stb_models.OptionQuerySet:
return (
self.options
.qs()
.tagged_or_all(self.tags)
.order_by(*settings.OPTIONS_ORDERING)
)


class Filtered(Options):
def __init__(
self,
category: stb_models.Category,
tags: stb_models.TagQuerySet,
):
"""Filtered options by a category and tags."""
self.filtered = TagsFiltered(
CategoryFiltered(
All(),
category,
),
tags,
)

def qs(self) -> stb_models.OptionQuerySet:
return self.filtered.qs()


class Searched(Options):

LOOKUPS = [
Expand Down
13 changes: 13 additions & 0 deletions stroyprombeton/context/tags.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from catalog import context
from stroyprombeton import models as stb_models

# @todo #744:30m Move all tags related context classes in this file.


class All(context.Tags):

def __init__(self, qs: stb_models.TagQuerySet = None):
self._qs = qs or stb_models.Tag.objects.all()

def qs(self) -> stb_models.OptionQuerySet:
return self._qs
35 changes: 29 additions & 6 deletions stroyprombeton/tests/tests_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -741,13 +741,36 @@ class ProductPrice(TestCase):

fixtures = ['dump.json']

def test_price_list(self):
"""Context for pdf generation should include Category and Products."""
self.response = self.client.get('/gbi/categories/1/pdf/')
def setUp(self):
self.category = models.CategoryPage.objects.filter(level=0).first()
self.response = self.client.get(
reverse('product_pdf', args=(self.category.id,))
)
self.context = self.response.context

def test_content_type(self):
self.assertEqual(self.response['Content-Type'], 'application/pdf')

def test_category_name(self):
self.assertEqual(self.context['category'].name, self.category.name)

def test_products(self):
self.assertIsInstance(self.context['products'], models.OptionQuerySet)
self.assertGreater(self.context['products'].count(), 100)

def test_tags_are_grouped(self):
for group, tags in self.context['group_tags_pairs']:
for tag_ in tags:
self.assertEqual(group, tag_.group)

def test_product_tags(self):
tags = set(chain.from_iterable(
grouped_tags
for _, grouped_tags in self.context['group_tags_pairs']
))

self.assertTrue(self.response['Content-Type'] == 'application/pdf')
self.assertTrue(self.response.context['category'].name == CATEGORY_ROOT_NAME)
self.assertTrue(len(self.response.context['products']) > 100)
for product in self.context['products'].filter(tags__isnull=False):
self.assertTrue(tags & set(product.tags.all()))


@tag('fast', 'catalog')
Expand Down
28 changes: 17 additions & 11 deletions stroyprombeton/views/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from catalog import context
from catalog.views import catalog
from images.models import Image
from pages import context as pages_context
from pages.models import CustomPage, ModelPage
from pages.templatetags.pages_extras import breadcrumbs as get_page_breadcrumbs
from stroyprombeton import context as stb_context, models, exception, request_data
Expand Down Expand Up @@ -192,24 +193,29 @@ class ProductPDF(PDFTemplateView, DetailView):

def get(self, *args, **kwargs):
self.object = self.get_object()
return super(ProductPDF, self).get(*args, **kwargs)
return super().get(*args, **kwargs)

def get_context_data(self, **kwargs):
context = super(ProductPDF, self).get_context_data(**kwargs)
category = context[self.context_object_name]
context_ = super().get_context_data(**kwargs)
category = context_[self.context_object_name]

products = (
models.Product.objects
.active()
.filter_descendants(category)
# use `OPTIONS_ORDERING` instead
# .order_by(*settings.PRODUCTS_ORDERING)
options_ = stb_context.options.CategoryFiltered(
stb_context.options.All(),
category
)
grouped_tags = context.tags.GroupedTags(
tags=stb_context.TagsByOptions(
stb_context.tags.All(),
options_.qs(),
)
)

return {
**context,
**context_,
**pages_context.Contexts([
options_, grouped_tags,
]).context(),
'category': category,
'products': products,
}


Expand Down
3 changes: 1 addition & 2 deletions templates/catalog/product_pdf_price.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<html lang="ru">
<head>
<meta charset="UTF-8">

<style>
* {
font-family: Arial, "Helvetica Neue", Helvetica, sans-serif;
Expand Down Expand Up @@ -37,7 +36,6 @@
td:not(:last-child) {
border-right: 1px solid #000;
}

.text-center {
text-align: center;
}
Expand All @@ -57,6 +55,7 @@ <h3 class="text-center">{{ base_url }}{{ category.url }}</h3>
</tr>
</thead>
<tbody>
{# @todo #744:60m Render an option's tags for pdf price list #}
{% for product in products %}
<tr id="{{ product.id }}">
<td>
Expand Down

2 comments on commit 3ca7da2

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on 3ca7da2 Jul 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 744-1635fcf3 discovered in stroyprombeton/context/tags.py and submitted as #755. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

@0pdd
Copy link
Collaborator

@0pdd 0pdd commented on 3ca7da2 Jul 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Puzzle 744-aee0ac14 discovered in templates/catalog/product_pdf_price.html and submitted as #756. Please, remember that the puzzle was not necessarily added in this particular commit. Maybe it was added earlier, but we discovered it only now.

Please sign in to comment.