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

发布于:2022-12-10 ⋅ 阅读:(685) ⋅ 点赞:(0)

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

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

问题概述

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

      ftyName = request.GET['ftyName']
      type= request.GET['type']
      pvPanelInfo = PvPanel.objects.get(factory=factory, type=type)
      print(type(pvPanelInfo))

后续需要把pvPanelInfo 的<class 'django.db.models.query.QuerySet'>格式转换成json格式

报错

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

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

问题解决

get获取改成filter获取数据

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

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

        # 查询集展开为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

方法二(给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

返回示例:

            {
                "factory": "宇宙牌光伏板",
                "type": "WH144P6-450",
                "length": 2094,
                "width": 1038
            }

但是这样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"]   #自定义返回字段

调用

from photovoltaicCalculation.toJson import PvPaneltoJSON  #导入刚写类
    pvPanel_data = PvPaneltoJSON(pvPanelInfo, many=True)
    print(pvPanel_data)
    data["data"]["pvPanelList"] = pvPanel_data.data

返回结果

            {
                "factory": "宇宙牌光伏板",
                "type": "WH144P6-450",
                "length": 2094,
                "width": 1038
            }

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))
#<class 'rest_framework.serializers.ListSerializer'>
print(type(book_one_ser))
#<class 'app01.ser.BookModelSerializer'>
 
# 对象的生成--》先调用类的__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)

问题总结

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

json.dumps 和json.loads()
dict转str str转成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

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

本文含有隐藏内容,请 开通VIP 后查看

网站公告

今日签到

点亮在社区的每一天
去签到