Repository: fidals/shopelectro

Issue:
models.py:77-78: Use MatrixBlock in the matrix view. Get...
The puzzle `880-51a8e904` from #880 has to be resolved: 

https://github.com/fidals/shopelectro/blob/6ed077725bf1891cd003097b5acaab3220274046/shopelectro/models.py#L77-L78

The puzzle was created by Artemiy on 04-Jul-19. 

Estimate: 60 minutes,  role: DEV. 

If you have any technical questions, don't ask me, submit new tickets instead. The task will be \"done\" when the problem is fixed and the text of the puzzle is _removed_ from the source code. Here is more about [PDD](http://www.yegor256.com/2009/03/04/pdd.html) and [about me](http://www.yegor256.com/2017/04/05/pdd-in-action.html). 



Discussion:
@artemiyds2 @duker33 please pay attention to this new issue.

Resolving patch:
diff --git a/shopelectro/migrations/0037_populate_matrixblock.py b/shopelectro/migrations/0037_populate_matrixblock.py
new file mode 100644
--- /dev/null
+++ b/shopelectro/migrations/0037_populate_matrixblock.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+# Generated by Django 1.11.20 on 2019-07-04 09:54
+from __future__ import unicode_literals
+
+from django.db import migrations
+
+
+def migrate_forward(apps, schema_editor):
+    MatrixBlock = apps.get_model('shopelectro', 'MatrixBlock')
+    Category = apps.get_model('shopelectro', 'Category')
+
+    for c in Category.objects.filter(level=0):
+        MatrixBlock.objects.get_or_create(category=c)
+
+
+def migrate_backward(apps, schema_editor):
+    MatrixBlock = apps.get_model('shopelectro', 'MatrixBlock')
+    MatrixBlock.objects.all().delete()
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ('shopelectro', '0036_matrixblock'),
+    ]
+
+    operations = [
+        migrations.RunPython(migrate_forward, migrate_backward),
+    ]
diff --git a/shopelectro/models.py b/shopelectro/models.py
--- a/shopelectro/models.py
+++ b/shopelectro/models.py
@@ -100,11 +100,11 @@ class Meta:
 
     @property
     def name(self):
-        self.category.name
+        return self.category.name
 
     @property
     def url(self):
-        self.category.url
+        return self.category.url
 
     def rows(self) -> SECategoryQuerySet:
         rows = self.category.children.active()
diff --git a/shopelectro/views/catalog.py b/shopelectro/views/catalog.py
--- a/shopelectro/views/catalog.py
+++ b/shopelectro/views/catalog.py
@@ -1,5 +1,4 @@
 import typing
-from collections import OrderedDict
 
 from django import http
 from django.conf import settings
@@ -18,39 +17,13 @@
 from shopelectro.exception import Http400
 from shopelectro.views.helpers import set_csrf_cookie
 
-# block numeric indexes to limit
-MATRIX_BLOCKS_TO_LIMIT = [3, 5]
-MATRIX_BLOCK_SIZE = 7
-
 
 def category_matrix(request, page: str):
-    assert page == 'catalog'
-    roots = (
-        models.Category.objects
-        .bind_fields()
-        .active()
-        .filter(level=0)
-        .order_by('page__position', 'name')
-    )
-    matrix = OrderedDict()
-    for i, root in enumerate(roots):
-        children = root.children.active()
-        # Categories matrix is UI element supposed to preview
-        # the whole catalog structure at with a single page.
-        # The matrix consists of blocks.
-        # Every block is a list of categories with links.
-        # How the matrix looks like:
-        # https://github.com/fidals/shopelectro/issues/837#issuecomment-501161967
-
-        matrix[(root.name, root.url)] = (
-            children
-            if i not in MATRIX_BLOCKS_TO_LIMIT
-            else children[:MATRIX_BLOCK_SIZE]
-        )
     context_ = {
-        'matrix': matrix,
+        'matrix_blocks': models.MatrixBlock.objects.blocks(),
         'page': pages_models.CustomPage.objects.get(slug=page),
     }
+
     return render(request, 'catalog/catalog.html', context_)
 
 


Test patch:
diff --git a/shopelectro/management/commands/test_db.py b/shopelectro/management/commands/test_db.py
--- a/shopelectro/management/commands/test_db.py
+++ b/shopelectro/management/commands/test_db.py
@@ -63,6 +63,8 @@ def handle(self, *args, **options):
         children = self.create_children(2, roots)
         deep_children = self.create_children(2, children)
 
+        self.create_matrix(roots)
+
         groups = self.create_tag_groups()
         tags = self.create_tags(groups)
 
@@ -112,6 +114,11 @@ def create_root(count):
             for i in range(count)
         ]
 
+    @staticmethod
+    def create_matrix(categories):
+        for c in categories:
+            se_models.MatrixBlock.objects.create(category=c)
+
     @staticmethod
     def create_children(count, parents):
         name = 'Category #{} of #{}'
diff --git a/shopelectro/tests/tests_models.py b/shopelectro/tests/tests_models.py
--- a/shopelectro/tests/tests_models.py
+++ b/shopelectro/tests/tests_models.py
@@ -89,11 +89,7 @@ def test_get_brands_from_products(self):
             }
 
     def test_get_matrix_blocks(self):
-        roots = Category.objects.filter(level=0)
-        roots_count = roots.count()
-        for category in roots:
-            MatrixBlock.objects.create(category=category)
-
+        roots_count = Category.objects.active().filter(level=0).count()
         blocks = MatrixBlock.objects.blocks()
 
         # 2 queries: MatrixBlock + Category joined with CategoryPage
@@ -114,31 +110,32 @@ class MatrixBlockModel(TestCase):
 
     fixtures = ['dump.json']
 
+    def count_all_rows(self, block: MatrixBlock) -> int:
+        return block.category.children.active().count()
+
     def test_block_category_relation_uniqueness(self):
-        category = Category.objects.first()
+        block = MatrixBlock.objects.first()
 
         with self.assertRaises(IntegrityError):
-            MatrixBlock.objects.create(category=category)
-            MatrixBlock.objects.create(category=category)
+            MatrixBlock.objects.create(category=block.category)
 
     def test_unsized_rows_count(self):
-        block = MatrixBlock.objects.create(category=Category.objects.first())
+        block = MatrixBlock.objects.filter(block_size=None).first()
 
         self.assertEquals(
-            block.category.children.active().count(),
+            self.count_all_rows(block),
             block.rows().count(),
         )
 
     def test_sized_rows_count(self):
-        sized_category, oversized_category = Category.objects.all()[:2]
+        sized_block, oversized_block = MatrixBlock.objects.all()[:2]
 
         # block_size < category's children quantity
-        sized_block = MatrixBlock.objects.create(
-            category=sized_category,
-            block_size=sized_category.children.count() - 1,
-        )
-        self.assertNotEquals(
-            sized_category.children.active().count(),
+        sized_block.block_size = self.count_all_rows(sized_block) - 1
+        sized_block.save()
+
+        self.assertGreater(
+            self.count_all_rows(sized_block),
             sized_block.rows().count(),
         )
         self.assertEquals(
@@ -147,15 +144,14 @@ def test_sized_rows_count(self):
         )
 
         # block_size > category's children quantity
-        oversized_block = MatrixBlock.objects.create(
-            category=oversized_category,
-            block_size=oversized_category.children.count() + 1,
-        )
+        oversized_block.block_size = self.count_all_rows(oversized_block) + 1
+        oversized_block.save()
+
         self.assertEquals(
-            oversized_category.children.active().count(),
+            self.count_all_rows(oversized_block),
             oversized_block.rows().count(),
         )
-        self.assertNotEquals(
+        self.assertGreater(
             oversized_block.block_size,
             oversized_block.rows().count(),
         )