• Django数据库查询集数据(Queryset)转化为json,查询value和value_list的用法,json.loads和json.dumps


    先简单回顾一下json和字典的区别

    json字典
    json是一种格式字典(dict)是一种数据结构
    json是类字典的形式,里面的键必须是双引号的字符串dict字典里面的键单、双引号的字符串都可以
    json的key可以是有序、重复的字典(dict)的键(key)不可重复

    问题概述

    我们在用Django写api从数据库获取数据时,要转成json然后才能传给前端解析。
    其次,这样得到的是一张表中所有字段的值,在不需要所有字段的时候只会增大开销。后续直接封装我们需要的字段名称,而不是先获取完整查询集,再展开过滤得到我们需要的字段。

    语法User.objects.filter(id=request.user.id)userInfo2 = User.objects.get(id=request.user.id)
    返回类型
    解释获取查找参数匹配的所有对象,返回查询集获取单一唯一对象使用,返回对象

    无论返回哪种一般序列化(serializers.ModelSerializer)转换成json格式用作接口data返回

          ftyName = request.GET['ftyName']
          type= request.GET['type']
          pvPanelInfo = PvPanel.objects.get(factory=factory, type=type)
          print(type(pvPanelInfo))
    
    • 1
    • 2
    • 3
    • 4

    报错

    pvPanelInfo 返回的数据是PvPanel object (5)但是print(type(pvPanelInfo))会报如下的错误。

    raise TypeError(f'Object of type {o.__class__.__name__} '
    TypeError: Object of type TypeError is not JSON serializable
    
    • 1
    • 2

    这里出现的错误是因为用type作为变量名了,应该避免用python函数名作为变量名

    问题解决

    get获取改成filter获取数据

            ftyName = request.GET['ftyName']
            pvPanelType = request.GET['type']
            # print(ftyName, type(pvPanelType))
            pvPanelInfo = PvPanel.objects.filter(factory=ftyName, type=pvPanelType)
    
    • 1
    • 2
    • 3
    • 4

    方法一(最原始的方法):

            # 查询集展开为json数据
            pvPanel_data = []
            for pvPanel in pvPanelInfo:
                pvPanel_item = {
                    "factory": pvPanel.factory,
                    "type": pvPanel.type,
                    "length": pvPanel.length,
                    "width": pvPanel.width,
                }
                pvPanel_data.append(pvPanel_item)
            data["data"]["pvPanelList"] = pvPanel_data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    方法二(给filter后加个values):

            pvPanelInfo = PvPanel.objects.filter(factory=ftyName, type=pvPanelType).values("factory","type","length","width")
            # 查询集展开为json数据
            pvPanel_data = []
            for pvPanel in pvPanelInfo:
                pvPanel_data.append(pvPanel)
            data["data"]["pvPanelList"] = pvPanel_data
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    返回示例:

                {
                    "factory": "宇宙牌光伏板",
                    "type": "WH144P6-450",
                    "length": 2094,
                    "width": 1038
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    但是这样values很长

    方法三(直接按model层设置格式转换)

    新建toJSon.py
    from rest_framework import serializers  # 这就是express中的serializers
    # 序列化的表格也要导入进来
    from photovoltaicCalculation.models import PvPanel
    
    
    # 序列化获取数据库中的数据
    class PvPaneltoJSON(serializers.ModelSerializer):
        class Meta:
            depth = 1  # 序列化的深度
            model = PvPanel  # 数据表
            # fields = '__all__'    #返回所有字段
            fields = ["id", "factory", "type", "length", "width"]   #自定义返回字段
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    调用
    from photovoltaicCalculation.toJson import PvPaneltoJSON  #导入刚写类
        pvPanel_data = PvPaneltoJSON(pvPanelInfo, many=True)
        print(pvPanel_data)
        data["data"]["pvPanelList"] = pvPanel_data.data
    
    • 1
    • 2
    • 3
    • 4
    返回结果
                {
                    "factory": "宇宙牌光伏板",
                    "type": "WH144P6-450",
                    "length": 2094,
                    "width": 1038
                }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    many=True源码分析(引用)

    a. 传many=True,跟不传many=True,实例化的序列化器对象都不一样
    b. 通过__new__控制的

    # 序列化多条,需要传many=True
    book_ser=BookModelSerializer(books,many=True)
    book_one_ser=BookModelSerializer(book)
    print(type(book_ser))
    #
    print(type(book_one_ser))
    #
     
    # 对象的生成--》先调用类的__new__方法,生成空对象
    # 对象=类名(name=lqz),触发类的__init__()
    # 类的__new__方法控制对象的生成
     
     
    def __new__(cls, *args, **kwargs):
        if kwargs.pop('many', False):
            return cls.many_init(*args, **kwargs)
        # 没有传many=True,走下面,正常的对象实例化
        return super().__new__(cls, *args, **kwargs)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    问题总结

    json.loads()json.dumps()的区别

    json.dumps和json.loads()
    dict转strstr转成dict
    json.dumps 序列化时对中文默认使用的ascii编码,string=json.dumps(data,ensure_ascii=False)

    Django-ORM values、values_list区别

    官方链接查看 按ctrl+F搜索values

    values()values_list()
    values()得到的是一个字典形式的查询集(QuerySet),查询集是一个可迭代对象values_list() 结果为元祖型
    QuerySet转为list: city_list = list(cities) 再将list序列化为json: city_json = json.dumps(city_list)加上flat=True,返回的是单个值,而不是元祖
    values()得到的是一个字典形式的查询集(QuerySet),查询集是一个可迭代对象
    # values 结果为字典型
    books = Book.objects.filter(id__lt=6).values('number')
    [{'number': '1'}, {'number': '2'}, {'number': '3'}, {'number': '4'}, {'number': '5'}]
     
    # values_list 结果为元祖型
    books = Book.objects.values_list('number')
    [('1',), ('2',), ('3',), ('4',), ('5',)]
     
    # 获取某个字段所有值2
    books = Book.objects.values_list('number', flat=True)
    books = ['1', '2', '3', '4', '5']
     
    # 获取某个字段所有值(不重复)
    models = Book.objects.filter(group=group).values('number').distinct().order_by('number') #必须有order_by
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    先这样吧,应该还有更好的方法,欢迎留言

  • 相关阅读:
    Anaconda+PytorchGPU版本+CUDA+CUNN的下载与安装使用
    qemu-system-aarch64使用记录
    【直播笔记0629】 并发编程二:锁
    lancet的维护--涉及gradle升级,plugin开发,asm使用
    2020 Java工程师面试题汇总
    flink处理函数--副输出功能
    若依分离版——配置多数据源(mysql和oracle),实现一个方法操作多个数据源
    【学习笔记】云原生初步
    推荐算法 面试
    Spring Cloud 常用框架组件
  • 原文地址:https://blog.csdn.net/qq_44976531/article/details/126976953