1

我希望有人能帮帮忙。我想实现类似于您在分类网站或博客上看到的内容,其中您有一个带有类别(带有子类别的父类别)的侧边栏,以及该父类别和子类别中有多少分类广告或博客文章的计数。看起来像这样:

侧边栏:显示父类别和子类别中所有广告的计数

这是我的模型

class Category(models.Model):
    name = models.CharField(max_length=120, unique=True)
    slug = models.SlugField(null=False, editable=False)
    parent = models.ForeignKey('self', null=True, blank=True, related_name='child_set')

class Classified(models.Model):
    category = models.ForeignKey(Category, related_name='categories')
    title = models.CharField(max_length=255, null=False, unique=True, blank=False)
    price = models.CharField(max_length=10, null=False, blank=False, default=0)
    description = models.TextField(null=False, blank=True, editable=True)
    user = models.ForeignKey(User)
    sold = models.BooleanField(blank=True, default=False)
    slug = models.SlugField(max_length=255, null=False, editable=False)

这是我的模板标签:

class Categories(template.Node):
    def render(self, context):
        categories = Category.objects.filter(parent=None).order_by('parent')
        context['categories'] = categories
        return ''

这是我用于获取计数的模板过滤器:

# Parent Category Count
@register.filter
def parent_category_count(value):
    count = Classified.objects.select_related().filter(category__in=Category.objects.filter(parent=value)).exclude(sold=True).count()
    return count

# Child Category Count
@register.filter
def child_category_count(value):
    count = Classified.objects.select_related().filter(category=value).exclude(sold=True).count()
    return count

这是我的模板:

{% regroup categories by parent as cat_list %}

{% for parent in cat_list %}
    <ul class="category">
        {% for item in parent.list %}
            <li class="parent-category-item">
                {% block parent-category %}
                    {% if item|parent_category_count %}
                        <span class="category-count">{{ item|parent_category_count }}</span>
                    {% else %}
                    {% endif %}
                <a {% if item.name == category %}class="parent selected"{% else %}class="parent"{% endif %} href="{% url classifieds_home %}{{ item.slug }}/">{{ item.name }}</a>
                {% endblock %}
            </li>
            <ul {% if item.name == category %}class="child-categories"{% else %}class="child-categories hide"{% endif %}>
                {% for i in item.child_set.all %}
                    <li class="child-category-item">
                        {% block category_child %}
                            {% if i|child_category_count %}
                                <span class="category-count">{{ i|child_category_count }}</span>
                            {% else %}
                            {% endif %}
                        <a {% if i.name == child_category %}class="child selected"{% else %}class="child"{% endif %} href="{% url classifieds_home %}{{ item.slug }}/{{ i.slug }}/">{{ i.name }}</a>
                        {% endblock %}
                    </li>
                {% endfor %}
            </ul>
        {% endfor %}
    </ul>
{% endfor %}

我已经厌倦了使用模板标签,它适用于除计数之外的所有内容。我厌倦了使用自定义模板过滤器来获取每个类别的计数,但这需要很长时间(141.91 毫秒内有 277 个查询)。

所以我知道过滤器计数导致数据库被多次命中,这不好。如果子计数会随着父计数快速加载而起作用,那么一切都会起作用,但我猜这与父类别较少有关。

我也厌倦了在 Django 中使用 raw()、extra() 和 annotate() 但无济于事,除非我做得不对。我不确定目前最好的方法是什么,但我确信以前有人这样做过,我不必重新发明轮子。

4

0 回答 0