zoukankan      html  css  js  c++  java
  • 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__'
  • 相关阅读:
    对象接口
    final关键字
    面向对象----多态,抽象,接口
    面向对象中的继承、封装、构造与析构函数
    PHP类与对象
    JS项目
    AppStore IAP 客户端校验代码
    Android线程计时器实现
    Cocos2d-x java 通过jni调用c++的方法
    ios7 uuid的获取方法
  • 原文地址:https://www.cnblogs.com/venicid/p/11771095.html
Copyright © 2011-2022 走看看