递归计算所有子类别中的所有产品

2024-05-16 18:00:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我想列出所有主要类别(其父类别是None)及其直接子类别(仅限级别1的子类别)。我正在使用django-mptt对我的类别进行建模,到目前为止,我只能计算一个直接子类别中的产品。你知道吗

我的观点是这样的:

def show_categories(request):
    categories = Category.objects.filter(parent=None)
    return render(request, 'products/categories.html', {'categories': categories})

以及我的模板:

<div class='categories'>
  <ul>
  {% for category in categories %}
    <li class='category'><a href="/shop/category/{{ category.slug }}">{{ category.name }}</a></li>
    {% for child in category.get_children %}
      <li class='subcategory'><a href="/shop/category/{{ child.slug }}">{{ child.name }} ({{ child.product_set.get_queryset.count }})</a></li>
    {% endfor %}
  {% endfor %}
  </ul>
</div>

…所以这是这样的:

>>> from products.models import Product, Category
>>> c = Category(name='Books')
>>> c.save()
>>> c1 = Category(name='Textbooks', parent=c)
>>> c1.save()
>>> c2 = Category(name='Primary school', parent=c1)
>>> c2.save()
>>> p = Product(title='Math textbook', description='Math textbook for 4th grade', price=20, year=2018, category=c2)
>>> p.save()
>>> c.product_set.get_queryset().count()
0

…我希望它返回1。你知道吗

我需要统计“儿童”类别的所有产品及其后代,因此可能有书籍->;教科书->;小学,目前我只拿到教科书,我也需要拿到小学。你知道吗

是否可以递归地计算所有子类别中的所有产品?你知道吗

@编辑:

我的型号,按要求:

from django.db import models
from django.urls import reverse
from django.template.defaultfilters import slugify

from mptt.models import MPTTModel, TreeForeignKey


class Product(models.Model):
    title = models.CharField(max_length=200)
    description = models.TextField()
    price = models.DecimalField(decimal_places=2, max_digits=10)
    year = models.PositiveSmallIntegerField()
    image = models.ImageField(upload_to=get_image_path, blank=True, null=True)
    date_added = models.DateTimeField(auto_now=True, null=True)
    category = models.ForeignKey('Category', on_delete=models.CASCADE)
    slug = models.SlugField()

    def __str__(self):
        return self.title

    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('products:product-detail', kwargs={'id': self.id, 'slug': self.slug})

class Category(MPTTModel):
    parent = TreeForeignKey('self', on_delete=models.CASCADE, null=True, blank=True, related_name='children')
    name = models.CharField(max_length=255)
    slug = models.SlugField()

    class Meta:
        unique_together = (('parent', 'slug',))
        verbose_name_plural = 'categories'

    class MPTTMeta:
        order_insertion_by = ['name']

    def __str__(self):
        return self.name

    def save(self, *args, **kwargs):
        self.slug = slugify(self.name)
        super().save(*args, **kwargs)

    def get_slug_list(self):
        ancestors = self.get_ancestors(include_self=True)
        slugs = [ancestor.slug for ancestor in ancestors]
        new_slugs = []
        for idx, ancestor in enumerate(slugs, 1):
            new_slugs.append('/'.join(slugs[:idx]))
        return new_slugs

Tags: nameselftruegetmodelssavedef类别
2条回答

您正在使用django mptt,但没有充分利用它。MPTT算法的全部要点是,您不需要递归,您可以在一次遍历中计算后代计数之类的内容。它让您可以通过一个方法来访问:^{}。你知道吗

我在我的分类模型中添加了get_recursive_product_count方法:

def get_recursive_product_count(self):
    return Product.objects.filter(category__in=self.get_descendants(include_self=True)).count()

…并在这样的模板中使用:

<ul>
  {% for child in category.get_children %}
    <li class='subcategory'><a href="/shop/category/{{ child.slug }}">{{ child.name }} ({{ child.get_recursive_product_count }})</a></li>
  {% endfor %}
</ul>         

相关问题 更多 >