【问题标题】:Advanced filtering for many-to-many annotations多对多注释的高级过滤
【发布时间】:2022-01-12 17:49:30
【问题描述】:

我有以下型号:

class CloudObjects(models.Model):
    object_id = models.AutoField(primary_key=True)
    object_name = models.CharField(max_length=256)
    creation_time = models.DateTimeField()
    removed_date = models.DateTimeField(blank=True, null=True)
    item = models.ManyToManyField(BackupItems, db_table='cloud_object_items')

class BackupItems(models.Model):
    name = models.CharField(max_length=100)

我想为每个 BackupItem 注释,CloudObject 中最近的 creation_time 字段,用于计划将来在 removed_date 中删除的项目。 举个例子: CloudObject 看起来像这样。

object_id | object_name | creation_time | removed_date | item
1 | object_one_in_cloud | 2021-01-01 | 2021-10-01 | 1
2 | object_two_in_cloud | 2021-02-02 | 2099-12-31 | 1
3 | object_three_in_cloud | 2021-03-03 | 2099-12-31 | 1
4 | object_four_in_cloud | 2021-12-31 | 2022-01-01 | 1

对于上面的例子,我想用 3 进行注释,因为它在未来已经删除_date,这是最新鲜的项目(项目 2 也计划在未来被删除,但是3 是较新的)

现在我想在我的观点中对此进行注释。我尝试了不同的方法,但现在可以继续前进。 这是我尝试的最后一个:

from django.db.models import Subquery, OuterRef

class BackupListView(ListView):
    template_name = 'somefile.html'

    def get_queryset(self):
        last_item = CloudObjects.objects.filter(item=OuterRef("pk")).filter(removed_date__gte=timezone.now()).last()
        all_items = BackupItems.objects.annotate(last_backup=Subquery(last_item.get('creation_time')))
        return all_items

如何让它工作?

【问题讨论】:

    标签: django django-views django-queryset django-annotate


    【解决方案1】:

    docs中所述:

    (使用 get() 代替切片会失败,因为在子查询中使用查询集之前无法解析 OuterRef。)

    last 的行为与 get 类似,它尝试解析查询集,但 OuterRef 需要首先位于子查询中。这就是为什么它不起作用。所以应该像这样使用切片:

        def get_queryset(self):
            cloud_objects = CloudObjects.objects.filter(
                item=OuterRef("pk")
            ).filter(
                removed_date__gte=timezone.now()
            ).order_by(
                "-creation_time"
            )
    
            all_items = BackupItems.objects.annotate(
                last_backup_date=Subquery(
                    cloud_objects.values("creation_time")[:1]
                )
            )
            return all_items
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-05
      • 2015-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      • 1970-01-01
      • 2014-09-23
      相关资源
      最近更新 更多