【问题标题】:Use of select_related in simple query in django在 django 的简单查询中使用 select_related
【发布时间】:2021-12-16 21:20:04
【问题描述】:

我在 Django 中有一个模型,其中一个字段与教师模型具有 fk 关系。我在 django 中遇到了 select_related 并想在我的视图中使用它。但是,我不确定是否在我的查询中使用它。

我的模型:

class Teacher(models.Model):
    name = models.OneToOneField(max_length=255, default="", blank=True)
    address = models.CharField(max_length=255, default="", blank=True)
    college_name = models.CharField(max_length=255, default="", blank=True)



class OnlineClass(models.Model):
    teacher = models.ForeignKey(Teacher,on_delete=models.CASCADE)                               
    

我的看法:

def get(self, request,*args, **kwargs):
   
    teacher = self.request.user.teacher
    classes = Class.objects.filter(teacher=teacher) #confusion is here..............
    serializer_class = self.get_serializer_class()
    serializer = serializer_class(classes,many=True)
    return Response(serializer.data,status=status.HTTP_200_OK)

我已经评论了问题的行或部分。所以我想列出那个老师的所有课程。在这里,我使用了过滤器。但是我们可以在这里使用 select_related 吗?我的理解是,如果我还想显示教师模型的另一个字段,例如 name 或 college_name,那么我必须使用它。否则我的做法是正确的。另外,select_related只用于get api,不用于post api,对吗??

【问题讨论】:

    标签: django api django-rest-framework django-views django-select-related


    【解决方案1】:

    首先,获取每位教师所有课程的最简单方法是使用related_name attribute (https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ForeignKey.related_name)。

    
    class OnlineClass(models.Model):
        teacher = models.ForeignKey(
           Teacher,
           on_delete=models.CASCADE, 
           related_name='classes'
        ) 
    
    
    # All classes of a teacher
    teacher.classes.all()
    

    当使用select_related 时,新的 sql 连接被添加到 Django 内部 SQL 查询中。有助于减少数据库引擎的工作量,快速获取数据,是的,只是为了读取。

    
    for obj in OnlineClass.objects.all():
       # This hits the database every cycle to get the teacher data,
       # with a new query like: select * from teacher_table where id = ...
       print(obj.teacher) 
    
    
    for obj in OnlineClass.objects.select_related('teacher').all():
       # This don'ts hits the database. 
       # Previously, the Django ORM joined the 
       # OnlineClass and Teacher data with a single SQL query.
       print(obj.teacher) 
    
    
    

    我认为,在您的示例中,只有一位老师,使用“select_related”或不使用没有太大区别。

    【讨论】:

    • 如果我能做到teacher.classes.all() ...我可以将它用作模型下的属性,而不是为此编写get api(获取老师的所有课程)
    • classes 是返回 RelatedManager 的属性。他们的文档在这里:docs.djangoproject.com/en/3.2/ref/models/relations/…
    【解决方案2】:

    select_related 用于在执行查询时从相关对象中选择附加数据。它会导致更复杂的查询。但如果您必须访问相关数据,它会提高性能,因为不需要额外的数据库查询。

    请参阅文档here

    在您的代码中可以使用select_related,但效率会很低,因为您没有访问查询类的相关对象。所以使用select_related 会导致更复杂的查询而没有任何优势。

    如果你想使用select_related,语法应该是classes = Class.objects.select_related('teacher').filter(teacher=teacher)

    【讨论】:

      猜你喜欢
      • 2017-05-25
      • 2021-08-23
      • 1970-01-01
      • 2019-05-04
      • 2021-06-21
      • 2016-12-28
      • 2018-10-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多