python遍历queryset_Django-如何使用QuerySet进行筛选以获取对象的子集?

本文探讨了在Django中使用QuerySet的filter()方法时遇到的问题,即filter()返回的结果包含重复记录,而不是预期的不重复子集。作者通过示例展示了在尝试获取Kid对象的子集时,出现了重复的Bob记录。文章讨论了distinct()方法的使用以消除重复,但指出这可能导致效率降低。最后,作者提出filter()方法名称可能误导,并认为可能存在更有效的方法来构造查询。
摘要由CSDN通过智能技术生成

filter(**kwargs) Returns a new QuerySet containing objects that match

the given lookup parameters.

The lookup parameters (**kwargs) should be in the format described in

Field lookups below. Multiple parameters are joined via AND in the

underlying SQL statement.

我认为它将返回原始集合中的项的子集。

然而,我似乎遗漏了一些东西,如下示例的行为与我预期的不同:>>> kids = Kid.objects.all()

>>> tuple(k.name for k in kids)

(u'Bob',)

>>> toys = Toy.objects.all()

>>> tuple( (t.name, t.owner.name) for t in toys)

((u'car', u'Bob'), (u'bear', u'Bob'))

>>> subsel = Kid.objects.filter( owns__in = toys )

>>> tuple( k.name for k in subsel )

(u'Bob', u'Bob')

>>> str(subsel.query)

'SELECT "bug_kid"."id", "bug_kid"."name" FROM "bug_kid" INNER JOIN "bug_toy" ON ("bug_kid"."id" = "bug_toy"."owner_id") WHERE "bug_toy"."id" IN (SELECT U0."id" FROM "bug_toy" U0)'

正如您在上面的subsel中看到的,结果返回了重复的记录,这不是我想要的。我的问题是,获取子集的正确方法是什么?(注意:按定义设置不会有同一对象的多个引用)

关于为什么的解释也很好,因为对我来说,filter意味着用Python中的内置函数filter()可以实现什么。也就是说:获取满足需求的元素(或者换句话说,丢弃不满足需求的元素)。这个定义似乎不允许引入/复制对象。

我知道完全可以distinct(),但这仍然会导致相当难看(而且可能比可能慢)的查询:>>> str( subsel.distinct().query )

'SELECT DISTINCT "bug_kid"."id", "bug_kid"."name" FROM "bug_kid" INNER JOIN "bug_toy" ON ("bug_kid"."id" = "bug_toy"."owner_id") WHERE "bug_toy"."id" IN (SELECT U0."id" FROM "bug_toy" U0)'

Mymodels.py完整性:from django.db import models

class Kid(models.Model):

name = models.CharField(max_length=200)

class Toy(models.Model):

name = models.CharField(max_length=200)

owner = models.ForeignKey(Kid, related_name='owns')

编辑:

在与@limelight聊天之后,我们得出的结论是,我的问题是我希望filter()按照字典的定义进行操作。也就是说,它在Python或任何其他理智的框架/语言中是如何工作的。

更准确地说,如果我设置了A = {x,y,z}并调用了A.filter( ),我就不会期望任何元素被复制。但对于Django的QuerySet,它的行为如下:A = {x,y,z}

A.filter( )

# now A i.e. = {x,x}

因此,首先问题是方法名不合适(类似于match()的方法会更好)。

第二件事是,我认为创建比Django允许的更有效的查询是可能的。我可能是错的,如果我有一点时间,我可能会试图检查这是否是真的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值