用于过滤空类别的上下文处理器

时间:2019-05-25 09:50:18

标签: python django-models django-queryset django-2.2

在我的博客中,帖子根据类别进行了划分。我从类别列表中排除了名为“未分类”的类别,现在我想排除空类别。

在context_processor中,我可以正常运行以下查询:

MyCategory.objects.exclude(category_name="Uncategorized")

我尝试过这样的查询:

def myblog_menu(request):

    myblog_menu_link = MyCategory.objects.exclude(category_name="Uncategorized").filter(category_name__category_set__isnull=True)
    return {
        'myblog_menu_link': myblog_menu_link,
    }

但是我看到这个错误:

  

CharField不支持的查找'category_set'或在字段上加入   不允许。

我该如何解决?

models.py

class MyCategory(models.Mode):
  category_name = models.CharField(...)
  .
  .
  :

class BlogPost(models.Mode):
  title = models.CharField(...)
  category = models.ForeignKey(MyCategory, related_name="category_set", ....)
  .
  .
  :

1 个答案:

答案 0 :(得分:1)

您可以排除以下内容为空的类别:

MyCategory.objects.exclude(
    category_name='Uncategorized'
).filter(
    category_set__isnull=False
).distinct()

这将因此生成如下查询:

SELECT DISTINCT mycategory.*
FROM mycategory
INNER JOIN blogpost ON mycategory.id = blogpost.category_id
WHERE NOT (mycategory.category_name = 'Uncategorized')
AND blogpost.id IS NOT NULL

因此,我们在这里指定如果我们用LEFT OUTER JOIN制作一个BlogPost,那应该是空的。这里的查询是INNER JOIN,这是一种优化,因为如果我们过滤掉可为空的变量,那么很显然我们不必首先生成那些空变量。

话虽这么说,我强烈建议您将related_name外键的category更改为blogpost_set,或直接保留。 related_name是对象的名称,Category没有category_set,它有一组blogposts

class BlogPost(models.Mode):
  title = models.CharField(...)
  category = models.ForeignKey(MyCategory, related_name='blogpost_set', ....)

在这种情况下,查询为:

MyCategory.objects.exclude(
    category_name='Uncategorized'
).filter(
    blogpost_set__isnull=False
).distinct()