简体   繁体   English

django中简单查询中select_related的使用

[英]Use of select_related in simple query in django

I have a model in Django in which a field has a fk relationship with the teacher model.我在 Django 中有一个模型,其中一个字段与教师模型有 fk 关系。 I have came across select_related in django and want to use it in my view.我在 django 中遇到了 select_related 并想在我看来使用它。 However, I am not sure whether to use it in my query or not.但是,我不确定是否在我的查询中使用它。

My models:我的模型:

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)                               
    

My view:我的看法:

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)

I have commented on the line or the section of the problem.我已经评论了问题的行或部分。 So I wanted to list all the classes of that teacher.所以我想列出那个老师的所有课程。 Here I have used filter.在这里我使用了过滤器。 But can we use select_related here??但是我们可以在这里使用 select_related 吗? What I understood is if I want to show another fields of teacher model as well, for eg name or college_name, then I have to use it.我的理解是,如果我还想显示教师模型的另一个领域,例如姓名或大学名称,那么我必须使用它。 Otherwise the way I have done it is correct.否则我这样做的方式是正确的。 Also, select_related is only used for get api not for post api, is that correct??另外,select_related 只用于 get api 而不是 post api,对吗??

First, the easiest way to get all classes per teacher is by using the related_name attribute ( https://docs.djangoproject.com/en/3.2/ref/models/fields/#django.db.models.ForeignKey.related_name ).首先,获取每位教师所有课程的最简单方法是使用related_name attributehttps://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()

When select_related is used, new sql joins are added to the Django internals SQL query.当使用select_related ,新的 sql 连接被添加到 Django 内部 SQL 查询中。 It is useful to reduce the workload in the database engine, getting the data quickly, and yes, is only for reading.减少数据库引擎的工作量,快速获取数据很有用,是的,只是为了读取。


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) 


I think that, in your example, with only one teacher, using "select_related" or not don't make big difference.我认为,在你的例子中,只有一位老师,使用“select_related”与否没有太大区别。

select_related is used to select additional data from related objects when the query is executed. select_related用于在执行查询时从相关对象中选择附加数据。 It results in a more complex query.这会导致更复杂的查询。 But it boosts performance if you have to access related data, since no additional database queries will be required.但是如果您必须访问相关数据,它会提高性能,因为不需要额外的数据库查询。

See documentation here .请参阅此处的文档。

In your code it would be possible to use select_related , but it would be inefficient, because you're not accessing related objects of the queried classes.在您的代码中,可以使用select_related ,但效率低下,因为您没有访问查询类的相关对象。 So using select_related would result in a more complex query without any advantage.因此,使用select_related会导致更复杂的查询而没有任何优势。

If you wanted to use select_related , the syntax would be classes = Class.objects.select_related('teacher').filter(teacher=teacher)如果你想使用select_related ,语法将是classes = Class.objects.select_related('teacher').filter(teacher=teacher)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM