如何将 django 的 Q 与 django taggit 一起使用?

     2023-02-23     174

关键词:

【中文标题】如何将 django 的 Q 与 django taggit 一起使用?【英文标题】:How do I use django's Q with django taggit? 【发布时间】:2013-06-30 11:49:56 【问题描述】:

我有一个标有“一”和“二”的 Result 对象。当我尝试查询标记为“一”“二”的对象时,我什么也得不到:

q = Result.objects.filter(Q(tags__name="one") & Q(tags__name="two"))
print len(q) 
# prints zero, was expecting 1

为什么它不适用于 Q?我怎样才能让它发挥作用?

【问题讨论】:

【参考方案1】:

在示例中,您对两个 python 对象(查询集)进行了结束。这适用于任何记录,不一定适用于具有 onetwo 作为标签的同一记录。

ps:为什么要使用in 过滤器?

【讨论】:

谢谢。我已经编辑了我的问题以消除干扰和 __in 过滤器。【参考方案2】:

q = Result.objects.filter(tags_name_in=["one"]).filter(tags_name_in=["two"])

添加 .distinct() 如果需要多个唯一对象,则删除重复项

【讨论】:

【参考方案3】:

首先,这三个是一样的:

Result.objects.filter(tags__name="one", tags__name="two")
Result.objects.filter(Q(tags__name="one") & Q(tags__name="two"))
Result.objects.filter(tags__name_in=["one"]).filter(tags__name_in=["two"])

我认为名称字段是 CharField,没有记录可以同时等于“一”和“二”。

在 python 代码中,查询看起来像这样(总是错误,为什么你没有得到结果):

from random import choice

name = choice(["abtin", "shino"])

if name == "abtin" and name == "shino":

我们使用 Q 对象来实现 OR 或复杂查询

【讨论】:

在最近的 Django 版本中,第一个查询集抛出 SyntaxError: keyword argument repeated,第二个给出空结果,第三个确实有效,但需要链接查询集的次数未知。第三个已经在另一个答案中提到,__in 不是必需的。使用AND逻辑和Taggit通过多个标签过滤查询集的解决方案是什么? 不知道 SyntaxError,很酷。实际上抛出错误是合乎逻辑的。为什么有人应该做一个总是返回 None 的查询?【参考方案4】:

django-taggit 实现标记的方式本质上是通过多对多关系。在这种情况下,数据库中有一个单独的表来保存这些关系。它通常被称为“直通”或中间模型,因为它连接了两个模型。在 django-taggit 的情况下,这称为TaggedItem。所以你有 Result 模型这是你的模型,你有两个模型 TagTaggedItem 由 django-taggit 提供。

当您进行诸如Result.objects.filter(Q(tags__name="one")) 之类的查询时,它会转换为在 Result 表中查找在 TaggedItem 表中具有对应行的行,而在 Tag 表中具有 name="one" 的对应行。

尝试匹配两个标签名称将转化为在 Result 表中查找在 TaggedItem 表中具有对应行的行,在 Tag 表中具有 name="one" 和 name= 的对应行“二”。您显然永远不会拥有它,因为您连续只有一个值,它要么是“一”,要么是“二”。

这些细节在 django-taggit 实现中是隐藏的,但只要对象之间存在多对多关系,就会发生这种情况。

要解决此问题,您可以:

选项 1

每次评估结果的标签后查询标签,正如其他人的答案中所建议的那样。这对于两个标签可能没问题,但当您需要查找设置了 10 个标签的对象时就不好了。这是执行此操作的一种方法,它会导致两个查询并为您提供结果:

# get the IDs of the Result objects tagged with "one"
query_1 = Result.objects.filter(tags__name="one").values('id')
# use this in a second query to filter the ID and look for the second tag.
results = Result.objects.filter(pk__in=query_1, tags__name="two")

您可以通过单个查询来实现这一点,因此您只需从应用程序到数据库的一次行程,如下所示:

# create django subquery - this is not evaluated, but used to construct the final query
subquery = Result.objects.filter(pk=OuterRef('pk'), tags__name="one").values('id')
# perform a combined query using a subquery against the database
results = Result.objects.filter(Exists(subquery), tags__name="two")

这只会访问一次数据库。 (注意:过滤子查询需要 django 3.0)。

但您仍然只能使用两个标签。如果需要检查10个或更多标签,上面的确实不可行...

选项 2

改为直接查询关系表并以提供对象 ID 的方式聚合结果。

#  django-taggit uses Content Types so we need to pick up the content type from cache
result_content_type = ContentType.objects.get_for_model(Result)
tag_names = ["one", "two"]
tagged_results = (
    TaggedItem.objects.filter(tag__name__in=tag_names, content_type=result_content_type)
        .values('object_id')
        .annotate(occurence=Count('object_id'))
        .filter(occurence=len(tag_names))
        .values_list('object_id', flat=True)
)

TaggedItem 是 django-taggit 实现中包含关系的隐藏表。上面将查询该表并聚合所有引用“一”或“二”标签的行,按对象的 ID 对结果进行分组,然后选择对象 ID 具有您正在查找的标签数量的那些为。

这是一个单独的查询,最后会为您提供所有已使用两个标签标记的对象的 ID。无论您需要 2 个标签还是 200 个标签,这也是完全相同的查询。

请查看此内容,如果有任何需要澄清的地方,请告诉我。

【讨论】:

这应该在他们的文档中,因为我想用 AND 而不是 OR 搜索多个标签会经常使用。

如何使用 Django Querysets 和 Q() 与相同模型类型的对象进行比较?

】如何使用DjangoQuerysets和Q()与相同模型类型的对象进行比较?【英文标题】:HowcanIuseDjangoQuerysetsandQ()tocompareagainstobjectsofthesamemodeltype?【发布时间】:2014-01-1608:10:46【问题描述】:我有一个名为MyModel的Django模型。m是MyModel的一个... 查看详情

我如何将 count() 与 Q 对象一起使用?

】我如何将count()与Q对象一起使用?【英文标题】:HowcouldIusecount()withQobject?【发布时间】:2012-09-1604:35:12【问题描述】:我正在使用Django,我应该如何使用django.db.models中的Q对象和count()来使用查询?【问题讨论】:你想达到什么... 查看详情

django之f与q查询(代码片段)

...我们要对两个字段的值做比较,那该怎么做呢? answer:Django提供F()来做这样的比较。F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值。showtime(我们来演示以下啪)???1fromdjango.dbimportmodels23# 查看详情

Django 中复杂 Q 对象过滤器查询的奇怪行为

】Django中复杂Q对象过滤器查询的奇怪行为【英文标题】:StrangebehaviorwithcomplexQobjectfilterqueriesinDjango【发布时间】:2011-02-1216:25:52【问题描述】:您好,我正在尝试为Django编写一个标记系统,但今天我在过滤器或Q对象(django.db.model... 查看详情

django 查询集中的 Q 对象

...】:g=Goal.objects.filter(Q(title__contains=term)|Q(desc__contains=term))如何将user=request.user添加到我的filter?这不起作用:g=Goal.objects.filter(user=request. 查看详情

Django/Python DRY:使用 Q 对象和模型属性时如何避免重复代码

】Django/PythonDRY:使用Q对象和模型属性时如何避免重复代码【英文标题】:Django/PythonDRY:howtoavoidrepeatcodewhenworkingwithQobjectsandmodelattributes【发布时间】:2013-06-1721:29:19【问题描述】:我正在尝试构建一个搜索页面,该页面将允许用... 查看详情

如何将新的支付网关与 django-payments 集成?

】如何将新的支付网关与django-payments集成?【英文标题】:Howtointegratenewpaymentgatewayswithdjango-payments?【发布时间】:2018-10-3016:40:39【问题描述】:我想为我正在进行的个人Django项目集成付款。Saleor使用django-payments进行付款处理。... 查看详情

将 Django 与 VueJ 集成

...DjangowithVueJs【发布时间】:2018-03-2611:08:05【问题描述】:如何将Django与VueJs集成?集成Django和VueJs的标准方法是什么?任何人都可以提供项目结构和参考来​​学习【问题讨论】:将Vue与任何其他框架集成的方式相同。它与Django... 查看详情

如何将 vue.js 与 django 集成?

】如何将vue.js与django集成?【英文标题】:howtointegratevue.jswithdjango?【发布时间】:2019-10-2511:24:14【问题描述】:这是带有vue.js的单页应用程序,它进行了一些简单的计算,我试图在django中实现这个计算,但它没有给我想要的结... 查看详情

Django - 将列表转换为 Q 对象的组合 OR 的正确方法 [重复]

】Django-将列表转换为Q对象的组合OR的正确方法[重复]【英文标题】:Django-correctwaytoconvertlisttocombinedORforQobject[duplicate]【发布时间】:2018-04-0818:30:24【问题描述】:我有QueryDict列表\'value\':[\'1\',\'2\',\'3\',\'4\',\'5\']-元素数量未知。我... 查看详情

如何将 Django 与 Tornado 网络服务器一起使用?

】如何将Django与Tornado网络服务器一起使用?【英文标题】:HowuseDjangowithTornadowebserver?【发布时间】:2011-02-0120:08:03【问题描述】:【问题讨论】:【参考方案1】:非常简单(尤其是django1.4)。1-只需构建您的django项目(和应用... 查看详情

如何将 django-admin-bootstrapped 与 django 1.10 集成

】如何将django-admin-bootstrapped与django1.10集成【英文标题】:Howtointegratedjango-admin-bootstrappedwithdjango1.10【发布时间】:2017-02-1121:55:16【问题描述】:如何在django1.10中使用django-admin-bootstrapped。https://github.com/django-admin-bootstrapped 查看详情

如何将 Angular Material 图标资产路径与 Django 模板集成?

】如何将AngularMaterial图标资产路径与Django模板集成?【英文标题】:HowtointegratetheAngularMaterialiconassetpathwithDjangotemplate?【发布时间】:2017-08-2409:37:37【问题描述】:我使用Django作为Web系统的后端,使用Angularjs材料作为前端。在前... 查看详情

如何将 Django 的标记模板标签与 Google App Engine WebApp 框架一起使用

】如何将Django的标记模板标签与GoogleAppEngineWebApp框架一起使用【英文标题】:HowdoIuseDjango\'sMarkUpTemplatesTagswithGoogleAppEngineWebAppFramework【发布时间】:2011-06-2506:42:03【问题描述】:我正在使用适用于Django模板的GoogleAppEngineWebApp框架... 查看详情

在 Django 中使用 Vue:如何将 publicPath 与静态文件前缀分开

】在Django中使用Vue:如何将publicPath与静态文件前缀分开【英文标题】:UsingVuewithDjango:HowtoseparatepublicPathfromstaticfileprefix【发布时间】:2021-05-0221:46:31【问题描述】:我正在尝试将我现有且庞大的Django项目(该项目目前在前端的各... 查看详情

如何在Django中的jQuery发布后呈现上一页

】如何在Django中的jQuery发布后呈现上一页【英文标题】:HowtorenderpreviouspageafterjQuerypostinDjango【发布时间】:2012-10-2314:47:20【问题描述】:我正在构建一个将主题与问题与答案联系起来的网站。每个问题都与一个主题相关联,每... 查看详情

如何将 Stripe 支付网关与 Django Oscar 集成?

】如何将Stripe支付网关与DjangoOscar集成?【英文标题】:HowtointegrateStripepaymentsgatewaywithDjangoOscar?【发布时间】:2018-12-1700:21:19【问题描述】:我正在尝试将Stripe支付网关集成到Djangooscar的电子商务网站,该网站在线销售杂货等实... 查看详情

Django 查询:返回一个将转换为“AND (...)”的 Q 对象

】Django查询:返回一个将转换为“AND(...)”的Q对象【英文标题】:Djangoqueries:returnaQobjectthatwilltranslateto"AND(...)"【发布时间】:2018-11-1813:46:32【问题描述】:我正在为我们的网站编写一个简单的搜索,我需要根据一些条件... 查看详情