使用 ORM Django 过滤新更新的查询集返回空查询集
Posted
技术标签:
【中文标题】使用 ORM Django 过滤新更新的查询集返回空查询集【英文标题】:filter on new updated queryset return empty queryset using ORM Django 【发布时间】:2021-10-21 07:42:06 【问题描述】:当使用save()
函数循环模型中的queryset
和更新字段时,尝试对更新的查询集进行过滤,即使查询集中仍有满足条件的元素,过滤结果也会返回空。
请检查下面的代码。
qs = queryset.filter(status=models.BankTransfer.STATUS_NEW)
for bank_transfer in qs:
bank_transfer.status = models.BankTransfer.STATUS_APPROVED
bank_transfer.save()
顺便说一句,当我打印qs
时,它会返回结果,但我尝试使用first()
获取第一个对象,它返回无
for bank_transfer in qs.filter(purpose__status='pending_completed'):
bank_transfer.purpose.status = 'completed'
bank_transfer.purpose.save()
银行转账模式:
class BankTransfer(models.Model):
swift_code = models.CharField(max_length=200, blank=False, verbose_name=_('SWIFT'))
user = models.ForeignKey(User, blank=False, null=True, on_delete=models.SET_NULL)
amount = models.DecimalField(blank=False, default=D('0'), max_digits=11, decimal_places=2, verbose_name=_('Amount'))
purpose = models.ForeignKey('auction.Purpose', blank=True, null=True, on_delete=models.SET_NULL)
status = models.CharField(max_length=200, blank=False, null=False, choices=STATUS_CHOICES, verbose_name=_('Status'))
用途型号:
class Purpose(models.Model):
status = models.CharField(max_length=200, blank=False, null=True, choices=STATUS_CHOICES, verbose_name=_('Status'))
bla
bla
【问题讨论】:
您将所有项目状态从STATUS_NEW
设置为STATUS_APPROVED
,因此当您执行qs.filter(..)
时,它是空的,因为STATUS_NEW
已经没有项目了。
你能分享相关的模型吗(可能是BankTransfer
和Purpose
模型。
@WillemVanOnsem 确定一分钟
我添加了模型
【参考方案1】:
qs
是 QuerySet
与具有 status
STATUS_NEW
的项目。在第一个循环中,您更新所有这些项目,使它们具有STATUS_APPROVED
。
但QuerySet
本质上是您正在构建的查询。如果您调用qs.filter(purpose__status='pending_completed')
,那么您进行new 查询并查找具有status=STATUS_NEW
和 且purpose__status
等于pending_completed
的项目,这没有多大意义。
因此,您应该以相反的方式处理查询集:
qs = queryset.filter(status=models.BankTransfer.STATUS_NEW)
for bank_transfer in qs.filter(purpose__status='pending_completed'):
purpose = bank_transfer.purpose
purpose.status = 'completed'
purpose.save()
for bank_transfer in qs:
bank_transfer.status = models.BankTransfer.STATUS_APPROVED
bank_transfer.save()
我们可以批量更新以提高效率:
qs = queryset.filter(status=models.BankTransfer.STATUS_NEW)
Purpose.objects.filter(
bank_transfer__in=qs,
status='pending_completed'
).update(status='completed')
qs.update(
status=models.BankTransfer.STATUS_APPROVED
)
这会批量更新表,因此无需枚举 Django/Python 层中的对象,而是使用UPDATE …
查询。
【讨论】:
谢谢你,你总是对整个社区有帮助。我想我保留了一个带有查询集结果的变量,然后我可以对该结果进行查询,但这是错误的以上是关于使用 ORM Django 过滤新更新的查询集返回空查询集的主要内容,如果未能解决你的问题,请参考以下文章