ORM高阶补充:only, defer,select_related

Queryset官方文档:https://docs.djangoproject.com/en/1.11/ref/models/querysets/

1、需求1:只取某n列

1、方法1:values

 2、方法2:values_list

 3、方法3:only,defer

# 需求1:只取某n列
# 推荐  方法3:only

class Test1View(APIView):
    def get(self, request, *args, **kwargs):
        """只取某n列"""

        # 方法1: values  返回值:queryset=[ {1, 'alex'}, {2, 'jack'}]
        queryset = User.objects.all().values('id', 'username')
        print(queryset, type(queryset))  # <class 'django.db.models.query.QuerySet'>

        ser = UserSerializer(instance=queryset, many=True)
        print(ser, type(ser))  # <class 'rest_framework.serializers.ListSerializer'>

        print(ser.data, type(ser.data))  # <class 'rest_framework.utils.serializer_helpers.ReturnList'>
        return Response(ser.data)


        # 方法2:values_list    返回值:queryset=[ (1, 'alex'), (2, 'jack')]
        queryset = User.objects.all().values_list('id', 'username')
        print(queryset, type(queryset))

        ser = UserSerializer(instance=queryset, many=True)
        print(ser, type(ser))

        # 取数据error
        # print(ser.data, type(ser.data))
        return Response({})

        # 推荐
        # 方法3:only  defer   返回值:queryset=[obj,obj]  [<User: alex>, <User: jack>]
        queryset = User.objects.all().only('id', 'username')
        # queryset = User.objects.all().defer('username')   # 排除某几个
        print(queryset, type(queryset))

        # 取值
        for item in queryset:
            print(item.id,item.username)     # tip:only中没有age,可以取到age (不推荐)
                      #  1  alex

        # ser = UserSerializer(instance=queryset, many=True)
        # print(ser.data, type(ser.data))
        return Response({})
View Code

2、需求2: 打印所有用户姓名以及部门名称

1、方法1:all+跨表 (性能低)

2、方法2:主动创建关联关系 select_related:仅支持one2many

# b. 需求: 打印所有用户姓名以及部门名称
# https://docs.djangoproject.com/zh-hans/2.2/ref/models/querysets/#select-related


class TestView(APIView):
    def get(self, request, *args, **kwargs):
        # 方法1:性能低   all()  + 跨表
        result = User.objects.all().values('username', 'dp__title')  # 10次
                                   # select * from user
        for item in result: 
            print(item['username'], item['dp__title'])                # 1次

        # get + 跨表  只取一个
        u = User.objects.get(id=1)
        dpart = u.dp
        title = dpart.title
        print(u.username, title)  

        return Response({})

        
        # 方法2:主动创建关联关系
        result = User.objects.all().select_related('dp')
        # select * from user left join depart on user.dp_id = depart.id
        print(result,type(result))
        for item in result:
            print(item.username, item.dp.title)
        return Response({})
View Code

3、方法3:prefetch_related:2次单表查询,支持many2many

示例:
    class Depart(models.Model): 5个部门
        title = models.CharField(...)

    class User(models.Model):   10个用户
        name = models.CharField(...)
        email = models.CharField(...)
        dp = models.FK(Depart)
1.以前的你:11次单表查询

    result = User.objects.all()
    for item in result:
        print(item.name,item.dp.title)

2. seleted_related,主动做连表查询(1次链表)

    result = User.objects.all().seleted_related('dp')
    for item in result:
        print(item.name,item.dp.title)

    问题:如果链表多,性能越来越差。
3. prefetch_related:2次单表查询
    # select * from user ;
    # 通过python代码获取:dp_id = [1,2]
    # select * from depart where id in dp_id
    result = User.objects.all().prefetch_related('dp')
    for item in result:
        print(item.name,item.dp.title)

4、代码

models

from django.db import models

# Create your models here.

class Depart(models.Model):
    title = models.CharField(max_length=32)
    number = models.CharField(max_length=32)

    def __str__(self):
        return self.title

class User(models.Model):
    username = models.CharField(max_length=32)
    age = models.IntegerField()
    dp = models.ForeignKey(to=Depart, on_delete=models.CASCADE)
    def __str__(self):
        return self.username

序列化

# -*- coding: utf-8 -*-
from django.shortcuts import render

# Create your views here.
from rest_framework.views import APIView
from rest_framework.serializers import ModelSerializer
from rest_framework.response import Response

from app01.models import User, Depart


class UserSerializer(ModelSerializer):
    class Meta:
        model = User  # model表
        # fields = '__all__'  # 所有字段
        fields = ['id', 'username']


class DepartSerializer(ModelSerializer):
    class Meta:
        model = Depart
        fields = '__all__'
原文地址:https://www.cnblogs.com/venicid/p/11771095.html