我希望有人能帮帮忙。我想实现类似于您在分类网站或博客上看到的内容,其中您有一个带有类别(带有子类别的父类别)的侧边栏,以及该父类别和子类别中有多少分类广告或博客文章的计数。看起来像这样:
这是我的模型
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() 但无济于事,除非我做得不对。我不确定目前最好的方法是什么,但我确信以前有人这样做过,我不必重新发明轮子。