多对多注释的高级过滤
Advanced filtering for many-to-many annotations
我有以下型号:
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 中计划在 removed_date 中删除的项目的最新 creation_time 字段。
举个例子:
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 进行注释,因为它在未来有 removed_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
如何让它工作?
如docs
所述:
(Using get() instead of a slice would fail because the OuterRef cannot be resolved until the queryset is used within a Subquery.)
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
我有以下型号:
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 中计划在 removed_date 中删除的项目的最新 creation_time 字段。 举个例子: 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 进行注释,因为它在未来有 removed_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
如何让它工作?
如docs
所述:
(Using get() instead of a slice would fail because the OuterRef cannot be resolved until the queryset is used within a Subquery.)
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