Django从每个组的最新日期检索对象PersonPhoto

2024-05-09 01:29:04 发布

您现在位置:Python中文网/ 问答频道 /正文

My DB包含不同人员的护照图像。比如:

class Person(models.Model):
    pass

class PersonPhoto(models.Model):
    date_captured = models.DateField()
    person = models.ForeignKey(Person, null=False)

我想为每个人提取他最新拍摄日期的所有图像。 因此,如果人A有8月5日、5日、9日、11日、11日的照片,人B有8月7日、9日、13日、13日、19日、19日的图像,那么我想为人A获取8月11日的两幅图像,为人B获取8月19日的两幅图像

我目前的做法是:

specific_dates_queryset = Q()
for photo in PersonPhoto.objects.all().values('person_id').annotate(max_date=Max('date_captured')):
    specific_dates_queryset |= Q(person_id=photo["person_id"], date_captured=photo["max_date"])


for photo in PersonPhoto.objects.filter(specific_dates_queryset).order_by("person_id"):
    print(f"image for person {photo.person_id}, of date {photo.date_captured}")

我们的想法是首先为每个人找到照片的最新日期,然后在一个新的查询中从这些日期为这些人获取这些图像

是否有一个更简单的解决方案可以在数据库中完成所有工作,并避免冗余查询和数据获取


Tags: 图像idfordatemodelmodelsclassperson
2条回答

在单个查询中完成此操作的一种简单方法是使用相关人员的最新日期为每张照片添加注释,然后根据注释进行过滤。这将返回查询集中所有需要的PersonPhoto

from django.db.models import Max, F

PersonPhoto.objects.annotate(
   latest=Max('person__personphoto__date_captured')
).filter(
    date_captured=F('latest')
)

我不确定注释的性能如何,这可能取决于您使用的数据库和数据的性质

您可以预取一个人的所有相关照片,并根据此人的最新拍摄日期进行过滤,如下所示:

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

person_qs = Person.objects.annotate(
    latest_photo_date=Max('personphoto__date_captured')
).prefetch_related(
    Prefetch(
        'personphoto_set',
        queryset=PersonPhoto.objects.annotate(
            person_latest_photo_captured=Max('person__personphoto__date_captured')
        ).filter(
            date_captured=F('person_latest_photo_captured')
        ),
        to_attr='latest_photos',
    )
)

所有最新的PersonPhoto实例都将作为Person实例的latest_photos属性中的列表提供,因此您可以如下方式访问它们:

for person in person_qs:
    print(f'Latest images for {person.name} taken on {person.latest_photo_date}:')
    for photo in person.latest_photos:
        print(f'Photo ID: {photo.id} - Captured at: {photo.date_captured}')
    print()

输出:

Latest images for B taken on 2021-08-19:
Photo ID: 10 - Captured at: 2021-08-19
Photo ID: 11 - Captured at: 2021-08-19

Latest images for A taken on 2021-08-11:
Photo ID: 5 - Captured at: 2021-08-11
Photo ID: 4 - Captured at: 2021-08-11

这将总共执行两个查询,一个查询人员列表,另一个查询获取每个人的所有过滤相关照片

相关问题 更多 >

    热门问题