使用 ORM Django 过滤新更新的查询集 return 空查询集

filter on new updated queryset return empty queryset using ORM Django

当使用 save() 函数在模型中循环 queryset 和更新字段时,然后尝试对更新的查询集进行过滤,过滤结果 returns 为空,即使仍然有查询集中满足条件的元素。

请检查下面的代码。

qs = queryset.filter(status=models.BankTransfer.STATUS_NEW)
for bank_transfer in qs:
     bank_transfer.status = models.BankTransfer.STATUS_APPROVED
     bank_transfer.save()

顺便说一句,当我打印 qs 时,它 returns 有结果,但我尝试使用 first() 来获取第一个对象,它 returns None

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

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 <strong>qs.filter(purpose__status='pending_completed')</strong>:
    purpose = bank_transfer.purpose
    purpose.status = 'completed'
    purpose.save()

for bank_transfer in <strong>qs</strong>:
     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'
)<b>.update(</b>status='completed'<b>)</b>

qs<b>.update(</b>
    status=models.BankTransfer.STATUS_APPROVED
<b>)</b>

这会批量更新表,因此不会枚举 Django/Python 层中的对象,但会使用 UPDATE … 查询。