如何消除循环中django查询的低效性?

如何消除循环中django查询的低效性?,django,performance,django-queryset,Django,Performance,Django Queryset,如何提高以下代码的效率(例如,如何用查询替换循环) def get_question(datetime_now,questions_queryset,user): 最佳时间表=无 最佳问题=无 #如何消除以下循环并替换为查询? 问题中的问题\u查询集: 尝试: schedule=(schedule.objects) .filter(问题=问题,用户=用户) .latest(字段\u name='datetime'u added') 除ObjectDoesNotExist外: 附表=无 如果(计划

如何提高以下代码的效率(例如,如何用查询替换循环)

def get_question(datetime_now,questions_queryset,user):
最佳时间表=无
最佳问题=无
#如何消除以下循环并替换为查询?
问题中的问题\u查询集:
尝试:
schedule=(schedule.objects)
.filter(问题=问题,用户=用户)
.latest(字段\u name='datetime'u added')
除ObjectDoesNotExist外:
附表=无
如果(计划和(schedule.date\u show\u next>=datetime\u now)和
((不是最佳时间表)或
(schedule.datetime\u added>=最佳计划。datetime\u added)):
最佳时间表=时间表
最佳问题
返回最佳问题


models.py

来自django.contrib.auth.models导入用户
从django.db.models导入DateTimeField、ForeignKey、Model、TextField
课堂提问(模型):
问题=TextField()
课程表(模型):
datetime\u added=DateTimeField(自动\u now\u add=True)
datetime\u show\u next=DateTimeField(null=True,缺省=None)
问题=外键(问题)
user=ForeignKey(user,null=True)
您可以在本答案中使用like,也可以使用

这里有一种通过
预取实现此目的的方法:

schedules_prefetch = Prefetch(
        'schedule_set',
        queryset=Schedule.objects.filter(user=user))
for question in questions_queryset.prefetch_related(schedules_prefetch):
    try:
        # using max here so it wouldn't do another DB hit
        schedule = max(question.schedule_set.all(),
                       key=lambda x: x.datetime_added)
    except ValueError:
        schedule = None
下面是一个使用
子查询
的示例(它可能实际上不起作用,但会给您一个大致的想法):


这并不能解决为每个问题获取最新时间表的问题
from django.db.models import OuterRef, Subquery
schedules = (Schedule.objects
             .filter(user=user, question=OuterRef('pk'))
             .order_by('datetime_added'))
questions_queryset = (questions_queryset
                    .annotate(latest_schedule=Subquery(schedules[:1])))
for question in questions_queryset:
    schedule = question.latest_schedule
    # Get the question ids    
    question_ids = questions_queryset.values_list('id', flat=True)

    # get the beloved shedule
    schedule = Schedule.objects.filter(question__in=question_ids, user=user).latest(field_name='datetime_added')

    # You may opt for Schedule.objects.get() so as not to run into
    # the problem of multiple objects returned if all you need is strictly one schedule