Django - 在参数

时间:2015-05-27 13:54:28

标签: django django-models django-select-related

我先给我的模型然后写说明。

class Entry(models.Model):
    entry_text = models.TextField()

class Category(models.Model):
    user = models.ForeignKey(User)
    category_text = models.CharField(max_length=200)
    entries = models.ManyToManyField(Entry, through='CategoryEntry')

class CategoryEntry(models.Model):
    category = models.ForeignKey(Category)
    entry = models.ForeignKey(Entry)
    viewed = models.BooleanField(default=False)

所以我有Entry模型和Category模型,我在这里创建了中间模型CategoryEntry https://docs.djangoproject.com/en/1.7/topics/db/models/#extra-fields-on-many-to-many-relationships,因为我需要一个额外的字段"查看" (当用户第一次打开特定的Entry链接时标记为True。)

所以我创建了generic.ListView视图,其中显示了用户为自己创建的所有这些类别。我想要的是,在每个类别名称旁边显示,有多少条目以及他还没有查看过多少条目。 像:

Category   Total   Not_viewed
AAA        126     5
BBB        17      15

我已设法通过

显示模板中的总条目数
{% for category in categories %}
    {{ category.text }}
    {{ category.entries.count }}
{% endfor %}

在我看来,我有get_queryset喜欢

def get_queryset(self):
    categories = Category.objects.filter(user=self.request.user.id)[:]

    return categories

据我了解,那么最好的方法是以某种方式添加关于在get_queryset中查看的每个类别条目的额外信息。我一直在寻找,但没有找到任何有用的东西。用select_related,prefetch_related,annotate尝试了一些东西,但没有找到正确的方法来做到这一点。 知道它不对,但尝试了类似的东西和其他一些东西。

categories = Category.objects.filter(user=self.request.user.id).select_related('categoryentry').filter(categoryentry__viewed=False).count()
categories = Category.objects.filter(user=self.request.user.id).annotate(not_viewed_count=Count('categoryentry')).filter(not_viewed_count__viewed=False)

希望你明白我想要实现的目标。

2 个答案:

答案 0 :(得分:0)

CategoryEntry模型中,在类别字段中使用related_name,如下所示:

category = models.ForeignKey(Category, related_name="related_entry_categories")

现在,您可以在查询Category模型时使用此相关名称。例如:

from itertools import chain

categories_not_viewed = Category.objects.filter(user=self.request.user.id, related_entry_categories__viewed=False).annotate(num_not_viewed=Count('related_en‌​try_categories'))
categories_viewed = Category.objects.filter(user=self.request.user.id, related_entry_categories__viewed=True).extra(select={'num_not_viewed': 0})
categories = chain(list(categories_not_viewed), list(categories_viewed))

答案 1 :(得分:0)

最后我提出了这个解决方案:

categories = Category.objects.filter(user=self.request.user.id).extra(select = {
          "num_not_viewed" : """
          SELECT COUNT(*)
          FROM app_categoryentry
          WHERE app_categoryentry.category_id = app_category.id
          AND app_categoryentry.viewed = %d """ % 0,
        })

基于此资源的解决方案http://timmyomahony.com/blog/filtering-annotations-django/

如果有人有其他解决办法如何只用Django ORM获得相同的结果,我想知道。