使用 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 已经没有项目了。 你能分享相关的模型吗(可能是BankTransferPurpose模型。 @WillemVanOnsem 确定一分钟 我添加了模型 【参考方案1】:

qsQuerySet 与具有 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 过滤新更新的查询集返回空查询集的主要内容,如果未能解决你的问题,请参考以下文章

查询集 QuerySet

Django中模型

django查询集-17

django基础知识之模型查询:

Django orm总结

Django ORM 查询