django - Django:是否可以过滤通过ForeignKey链接的多个模型?

标签 django django-models django-queryset

我想为以下值和模型创建过滤排序混合:

class Course(models.Model):
    title = models.CharField(max_length=70)
    description = models.TextField()
    max_students = models.IntegerField()
    min_students = models.IntegerField()
    is_live = models.BooleanField(default=False)
    is_deleted = models.BooleanField(default=False)
    teacher = models.ForeignKey(User)

class Session(models.Model):
    course = models.ForeignKey(Course)
    title = models.CharField(max_length=50)
    description = models.TextField(max_length=1000, default='')
    date_from = models.DateField()
    date_to = models.DateField()
    time_from = models.TimeField()
    time_to = models.TimeField()

class CourseSignup(models.Model):
    course = models.ForeignKey(Course)
    student = models.ForeignKey(User)
    enrollment_date = models.DateTimeField(auto_now=True)

class TeacherRating(models.Model):
    course = models.ForeignKey(Course)
    teacher = models.ForeignKey(User)
    rated_by = models.ForeignKey(User)
    rating = models.IntegerField(default=0)
    comment = models.CharField(max_length=300, default='')
  • 类(class)可能是“离散数学1”
  • session 是与类(class)相关的各个类(例如1.简介,2。第一章,3期末考试等),并结合了日期/时间
  • CourseSignup是学生
  • 的“报名”
  • TeacherRating跟踪学生对老师的评分(类(class)完成后)

  • 我想实现以下功能
  • 按日期(最早的Session.date_from),Course.Name
  • 排序(升​​序,降序)
  • 筛选依据:日期(最早的Session.date_from和最后一个Session.date_to),平均TeacherRating(例如,最小值= 3),CourseSignups(例如,至少5个用户注册)
    (这些选项通过GET参数传递,例如sort = date_ascending&f_min_date = 10.10.12&...)

  • 您将如何为此创建函数?

    我试过使用
  • 非规范化(仅在类(class)中添加了所需过滤器/排序标准的字段,并在发生更改时对其进行了更新),但我对此并不满意(例如,每次TeacherRating之后都需要进行大量更新)。
  • ForeignKey查询(Course.objects.filter(session__date_from = xxx)),但稍后我可能会遇到性能问题。

    感谢您的小费!

  • 最佳答案

    除了将Q对象用于高级AND/OR查询之外,还要熟悉反向查找。

    当Django为外键关系创建反向查找时。在您的情况下,您可以使用两种方法之一获得属于类(class)的所有 session ,每种方法都可以过滤。

    c = Course.objects.get(id=1)
    sessions = Session.objects.filter(course__id=c.id) # First way, forward lookup.
    sessions = c.session_set.all() # Second way using the reverse lookup session_set added to Course object.
    

    您还需要熟悉annotate()aggregate(),它们使您可以计算字段以及对结果进行排序/过滤。例如,计数,总和,平均,最小值,最大值等。
    courses_with_at_least_five_students = Course.objects.annotate(
        num_students=Count('coursesignup_set__all')
    ).order_by(
        '-num_students'
    ).filter(
        num_students__gte=5
    )
    
    
    course_earliest_session_within_last_240_days_with_avg_teacher_rating_below_4 = Course.objects.annotate(
        min_session_date_from = Min('session_set__all')
    ).annotate(
        avg_teacher_rating = Avg('teacherrating_set__all')
    ).order_by(
        'min_session_date_from',
        '-avg_teacher_rating'
    ).filter(
        min_session_date_from__gte=datetime.now() - datetime.timedelta(days=240)
        avg_teacher_rating__lte=4
    )
    

    Q用于允许您在查询中进行逻辑与和逻辑或。

    关于django - Django:是否可以过滤通过ForeignKey链接的多个模型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13515960/

    相关文章:

    python - 在 django 查询集中排列键顺序

    模板中的django 1.1权限问题

    django - 将额外数据附加到 Django 中的 request.POST

    django - 聚合函数返回 AttributeError : 'Sum' object has no attribute 'lookup'

    django - 如何在Django中计算数据库表中的行数

    python - 使用类扩展 Django ModelForm

    django - 根据 Django 中另一个相关模型的 M2M 关系过滤相关字段

    python - Django REST Framework 3 中的附加序列化程序字段

    python - 关键字参数

    python - django 用户的用户名和电子邮件相同吗?