我有这样的模型ContentBuild
和ContentBuildDeviceGroupLink
:
# 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()
我想返回过去带有ContentBuildDeviceGroupLink
的最新release_date
对象,以及将来返回带有ContentBuildDeviceGroupLink
的所有release_date
对象。
我试图这样使用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)
答案 0 :(得分:2)
您不将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 :(得分:1)
您的第二次尝试已经结束,但是有两个问题:
first
对象,所以该对象是最早的 release_date
,而不是最近的 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'))
可能有一种更聪明的方法,但这似乎可行。