Задать вопрос

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

Уважаемые знатоки! Помогите решить проблему. Структура моделей такова:
Категория -> подкатегория -> подподкатегория -> объявление. Все через ForeignKey. Задача вывести количество объявлений в скобках в списке Категорий. В списке подкатегорий вывожу очень просто
{%for category in subcategory_list%}
      <li>{{category.title}}<span>{{category.subsubcategory.order_set.count}}</span></li>
 {%endfor%}

А вот с Категориями сложнее по моей логике пытался сделать так):
{%for subcategory in category.subcategory_set.all%}
      <li>{{subcategory.title}}<span>{{subcategory.subsubcategory_set.all.order_set.count}}</span></li>
{%endfor%}

Естественно не вышло)
  • Вопрос задан
  • 2954 просмотра
Подписаться 4 Простой 2 комментария
Пригласить эксперта
Ответы на вопрос 2
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;
Ответ написан
Astrohas
@Astrohas
Python/Django Developer
class Category(models.Model):
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children')


а Для того чтобы отобразить, сделайте собственный кастом тег, который будет генерировать это на стороне питона
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы