0

我会先给出我的模型,然后再写描述。

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-许多关系,因为我需要一个额外的字段“查看”(当用户第一次打开特定的条目链接时标记为 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)

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

4

2 回答 2

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))
于 2015-05-27T14:20:36.930 回答
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 获得相同的结果,我想知道。

于 2015-06-04T08:29:21.157 回答