簡體   English   中英

過去和將來所有的Django queryset過濾器

[英]Django queryset filter for most recent in the past and all in the future

上下文

我有這樣的模型ContentBuildContentBuildDeviceGroupLink

# models.py

class ContentBuild(models.Model):
    content_build_uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)


class ContentBuildDeviceGroupLink(models.Model):
    uuid = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, db_index=True)
    content_build_uuid = models.ForeignKey(ContentBuild, on_delete=models.CASCADE, related_name='content_build_deploy')
    group_uuid = models.ForeignKey(DeviceGroup, on_delete=models.CASCADE)
    preload_date = UnixDateTimeField()
    release_date = UnixDateTimeField()

目標

我想返回過去帶有release_date最新ContentBuildDeviceGroupLink對象,以及將來所有帶有release_date ContentBuildDeviceGroupLink對象。

我嘗試了什么

我試圖像這樣使用Q object

in_future = Q(release_date__gte=timezone.now())
recent_past = Q(release_date__lt=timezone.now()).order_by('-release_date')[0]

ContentBuildDeviceGroupLink.objects
.filter(in_future & recent_past)

這不起作用並引發錯誤:

'datetime.datetime' object has no attribute 'order_by'

如何過濾與該對象release_date在最近的過去,並與所有對象release_date的未來?

編輯

我更改了方法,因此首先獲取最近的對象,然后過濾所有大於或等於該日期的對象。 但是,當只有1個ContentBuild時,下面的queryset可以很好地工作,但是當有多個相關的ContentBuild時,返回所有較舊的對象。

recent_past = ContentBuildDeviceGroupLink.objects
    .filter(release_date__lte=timezone.now()).order_by('release_date').first()

ContentBuildDeviceGroupLink.objects.filter(release_date__gt=recent_past.release_date)

您不能將order_by與查詢集一起使用。 嘗試這個。

in_future = Q(release_date__gte=timezone.now())
recent_past = Q(release_date__lt=timezone.now())

ContentBuildDeviceGroupLink.objects.filter(
    in_future & recent_past
).order_by('-release_date').first()

您的第二次嘗試已經結束,但是有兩個問題:

  1. 因為您要從有序列表中刪除第first對象,所以那個人的release_date 最早 ,而不是最新的
  2. 使用gt而不是gte似乎有點懷疑...我很驚訝當只有一個ContentBuild時它拾取了任何東西

要在單個數據庫查詢中獲取它,您有兩個選項,具體取決於您的Django版本。 如果您使用的是django> = 2.0,則應該可以這樣做(我沒有一個項目,現在可以測試此項目):

from django.db.models import Max, Q, F

ContentBuildDeviceGroupLink.objects.annotate(
    start_date=Max('release_date', filter=Q(release_date__lt=timezone.now())
).filter(release_date__gte=F('start_date'))

如果您使用的是django <2.0,請嘗試以下操作:

from django.db.models import Subquery, F

recent_dates = ContentBuildDeviceGroupLink.objects.filter(
    release_date__lte=timezone.now()
).order_by('-release_date').values('release_date')

ContentBuildDeviceGroupLink.objects.annotate(
    start_time=Subquery(recent_dates[:1])
).filter(release_date__gte=F('start_time'))

可能有一種更聰明的方法,但這似乎可行。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM