• Как в django вывести в шаблон count всех объектов подподкатегории?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Django
    Седой и строгий
    Прежде всего, если используете иерархические структуры данных, то используйте их с django-mptt. Во-первых, это позволит работать с любым уровнем вложенности, в том числе неопределённым на этапе разработки и переменным в разных ветках. Во-вторых, это облегчит вам работу, предоставив простые и эффективные методы манипуляции ветками. Наконец, это позволит получать данные из БД наиболее быстрым и эффективным способом, с минимальной затратой ресурсов.

    Конкретно по вашей задаче решением в лоб было бы определить в модели свойство, возвращающее количество объявлений в дочерних категориях:
    class Category(models.Model):
        parent = TreeForeignKey('self', verbose_name=u'Родитель', null=True, blank=True, related_name='children')
        title = models.CharField(u'Название', max_length=100)
    
        @property
        def items_count(self):
            # получаем список идентификторов всех низлежащих категорий, включая интересующую нас
            ids = self.get_descendants(include_self=True).values_list('id')
            # возвращаем количество товаров, имеющих родителем категорию с идентификатором входящим
            # в список полученный строкой выше
            return Product.objects.filter(parent_id__in=ids).count()

    и потом вывести их в шаблоне как-то так
    <ul class="root">
        {% recursetree nodes %}
            <li>
                {{ node.title }}<span>{{ note.items_count }}</span>
                {% if not node.is_leaf_node %}
                    <ul class="children">
                        {{ children }}
                    </ul>
                {% endif %}
            </li>
        {% endrecursetree %}
    </ul>

    Но беда в том, что это квадратичный алгоритм, чем больше будет категорий отображаться на странице, тем больше запросов будет к базе при открытии этой страницы. Я так и не нашёл в Django лучшего решения для этого, чем делать сырой SQL запрос к базе:
    SELECT name, cp.p_count FROM catalog_category AS cc
    INNER JOIN LATERAL (
      SELECT cc.id AS id, SUM(products) AS p_count FROM (
        SELECT cc.id AS parent_id, category_id, COUNT(id) AS products
        FROM catalog_product
        WHERE category_id IN (
          SELECT id FROM catalog_category
          WHERE lft <= cc.rght AND lft >= cc.lft AND tree_id = cc.tree_id)
          GROUP BY category_id
        ) AS sub_cс
      GROUP BY parent_id
    ) AS cp
    USING(id) ORDER BY name;
    Ответ написан
    5 комментариев
  • Как скопировать файл в Ubuntu?

    FeNUMe
    @FeNUMe
    Просто используйте обычную версию pycharm, а не из snap пакета и делайте с файлами в ней что хотите.
    Ответ написан
    2 комментария
  • Не правильно отображается контент, как исправить?

    mrusklon
    @mrusklon
    Не получается? Яростно гугли!
    #fancy_outer{
        z-index: 999999;
    }
    Ответ написан
    1 комментарий