首页 > 解决方案 > 用于过滤空类别的上下文处理器

问题描述

在我的博客中,帖子是根据类别划分的。我已经从类别列表中排除了名为 Uncategorized 的类别,现在我想排除空的类别。

进入 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”或不允许加入该字段。

我该如何解决?

模型.py

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

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

标签: pythondjangodjango-modelsdjango-queryset

解决方案


您可以通过以下方式排除空类别:

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 JOINwith BlogPost,那应该是空的。这里的查询是 an INNER JOIN,这是一种优化,因为如果我们过滤掉可空值,那么很明显我们不必一开始就生成它们。

话虽如此,我强烈建议您将外键更改related_namecategoryblogpost_set或保持原样。是对象的related_name名称,aCategory没有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()

推荐阅读