我有两个模特:
class Gallery(models.Model):
site = models.ForeignKey(Site, related_name='galleries', on_delete=models.CASCADE)
created = models.DateTimeField(_('created'), auto_now_add=True)
class Photo(models.Model):
image = ImageField(verbose_name=_('image'), upload_to=upload_path)
gallery = models.ForeignKey(Gallery, related_name='photos', on_delete=models.CASCADE)
created = models.DateTimeField(_('created'), auto_now_add=True,)我想得到最后三张照片。每一张照片都应该分配到不同的画廊。
这个解决方案很有效,但也很慢。我能让它工作得更快吗?
limit = 3
photos = Photo.objects.annotate(
max_gallery_created=Max('gallery__photos__created'),
).filter(
gallery__site=site,
created=F('max_gallery_created'),
).order_by(
'-max_gallery_created',
)[:limit]我也会满意,如果我得到最后一张照片,从三个最后创建的画廊。我试过这样做:
galleries = Gallery.objects.filter(site=site).order_by('-created').values_list('id')[:limit]
photos = Photo.objects.filter(id__in=galleries)但这并不能阻止画廊再次发生。我考虑过以某种方式使用distinct(),但我不知道有多疯狂。
Django 1.11
编辑:
我想我应该为我所期望的结果树立一些榜样。
- Gallery1 (created 10.01.2019)
- PhotoA (created: 15.01.2019 at 12:00)
- PhotoB (created: 15.01.2019 at 11:00)
- PhotoC (created: 13.01.2019 at 11:00)
- Gallery2 (created 09.01.2019)
- PhotoD (created: 13.01.2019 at 10:00)
- PhotoE (created: 12.01.2019 at 10:00)
- PhotoF (created: 10.01.2019 at 10:00)
- Gallery3 (created 08.01.2019)
- PhotoG (created: 14.01.2019 at 11:00)
- PhotoH (created: 14.01.2019 at 11:00)
- PhotoI (created: 14.01.2019 at 11:00)
- Gallery4 (created 07.01.2019)
- PhotoJ (created: 14.01.2019 at 12:00)
- PhotoK (created: 12.01.2019 at 10:00)
- PhotoL (created: 12.01.2019 at 10:00)在这种情况下
我现在得到的:PhotoA, PhotoB, PhotoJ
我想要的:PhotoA, PhotoJ, PhotoG
如果我得到:PhotoA, PhotoD, PhotoG,我也会感到满意
发布于 2019-04-05 15:41:16
如果使用的是PostgreSQL,则可以使用一个嵌套查询从不同的图库获取最新的三张照片。为了提高效率,任何进一步的过滤器都应该添加到内部查询中:
photos = (Photo.objects
.filter(id__in=Photo.objects.filter(gallery__site=site)
.order_by('gallery', '-created')
.distinct('gallery').values('id'))
.order_by('-created')[:3]
)对于其他后端,您可以使用Bernhard提出的预取子查询,尽管他的解决方案将让您按照图库日期对所有图库进行排序,每个图库中都有最新的三张照片。
使用一个额外的筛选器,根据照片日期而不是图片库日期对图片库进行排序和限制,您可以获得与上面相同的结果:最新的3张照片,每个图片库仅限一张照片:
prefetch = Prefetch('photos', queryset=Photo.objects.filter(id__in=
Subquery(Photo.objects.filter(
gallery_id=OuterRef('gallery_id')
).order_by('-created').values_list('id', flat=True)[:1])))
galleries = (Gallery.objects
.filter(id__in=Gallery.objects
.order_by('-photos__created')
.distinct()[:3]
)
.order_by('-created')
.prefetch_related(prefetch)
)发布于 2019-04-05 13:53:58
从Django 1.11开始,您应该能够使用 Expressions和prefetch_related()的组合来完成这个任务。
from django.db.models import OuterRef, Subquery, Prefetch
subquery = Subquery(
Photo.objects.filter(
gallery_id=OuterRef('gallery_id')
).order_by('-created').values_list('id', flat=True)[:3])
galleries = Gallery.objects.order_by('-created').prefetch_related(
Prefetch('photos',
queryset=Photo.objects.filter(id__in=subquery).order_by('-created')))
for gallery in galleries:
for photo in gallery.photos.all(): # should now be the latest 3
print(photo)如果要将最新的照片获取到与photos不同的属性,则可以使用 class的to_attr参数。
https://stackoverflow.com/questions/55535936
复制相似问题