django 仅从查询集中获取类型的最新项

xe55xuns  于 2023-03-20  发布在  Go
关注(0)|答案(1)|浏览(90)

两种型号:

class University(models.Model):
    name = models.CharField("name", max_length = 48)
    city = models.ForeignKey(City, on_delete = models.CASCADE) 

class Course(models.Model):
    name = models.CharField("course name", max_length = 48)
    university = models.ForeignKey(University, on_delete = models.CASCADE)
    students = models.ManyToManyField(Student, related_name = "%(class)s_name", related_query_name = "student_course_qs", blank = True)
    online = models.BooleanField("online course", default = False)
    semester = models.PositiveIntegerField("choose 1-6", default = 1, choices = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)])
    time_update = models.DateTimeField("last info update", auto_now = True)

限制条件:如果Course具有students,则它不能是online,反之亦然。
如何获得给定city的所有Universities上的所有Courses的列表,其中Course上的最新条目包含students,而Course包含在第三个semester中?
我尝试过在University的不同组上循环,但这会导致大量的查询:

universities = University.objects.filter(city = City.objects.first())

wanted = []
for univ in universities:
    c = Course.objects.filter(university = univ).order_by("time_update").last()
    if c.semester == 3 and not c.online:
        wanted.append(c.id)

selected_courses = Courses.objects.filter(id__in = wanted)

我在这里看到的问题是,我创建了太多的查询,并且在universities的过滤器之后,它们就已经被分组了-我可以一个接一个地处理这些组而不重新创建查询吗?

ct3nt3jp

ct3nt3jp1#

您可以使用子查询:

from django.db.models import F, OuterRef, SubQuery

universities = (
    University.objects.filter(city=City.objects.first())
    .annotate(
        last_course_id=Subquery(
            Course.objects.filter(university_id=OuterRef('pk'))
            .order_by('-time_update')
            .values('pk')[:1]
        )
    )
    .filter(
        course__id=F('last_course_id'), course__semester=3, course__inline=True
    )
)
selected_courses = Course.objects.filter(
    id__in=[university.last_course_id for university in universities]
)

这里我们首先为每个University选择最后一个Course的主键,然后我们可以在JOIN的过滤中使用它,最后我们用一个额外的查询获取Courses

相关问题