django执行原始查询sql,并返回Dict字典例子


Posted in Python onApril 01, 2020

很多时候执行sql语句,数据比django的model来的快,但并不想关心返回的字段,例如你可以执行:select * from product这种sql,这里个方法将会返回与数据库列名相同的键值对 ,格式是这样子的:

result = [{“id”:1,”name”:”product1”},{“id”:2,”name”:”product2”}]

当然你还可以

import json
json.dumps(result )

返回一串json数据,是不是很完美。。。

# coding:utf-8
from django.db import connection, transaction

'''执行django原始sql语句 并返回一个数组对象'''
def executeQuery(sql):
 cursor = connection.cursor() # 获得一个游标(cursor)对象
 cursor.execute(sql)
 rawData = cursor.fetchall()
 print rawData
 col_names = [desc[0] for desc in cursor.description]
 print col_names

 result = []
 for row in rawData:
  objDict = {}
  # 把每一行的数据遍历出来放到Dict中
  for index, value in enumerate(row):
  print index, col_names[index], value
  objDict[col_names[index]] = value

  result.append(objDict)

 return result

补充知识:重写django的mysql驱动实现原生sql语句查询返回字典类型数据

在使用django的时候,有些需求需要特别高的查询效率,所以需要使用原生的sql语句查询,但是查询结果一般是一个元组嵌套元组。为了处理方便,需要从数据库查询后直接返回字典类型的数据。

这里使用的方法是继承django.db.backends.mysql驱动

首先在django项目下创建一个mysql文件夹,然后在这个文件夹下创建base.py。

base.py

from django.db.backends.mysql import base
from django.db.backends.mysql import features
from django.utils.functional import cached_property
 
class DatabaseFeatures(features.DatabaseFeatures):
 @cached_property
 def is_sql_auto_is_null_enabled(self):
  with self.connection.cursor() as cursor:
   cursor.execute('SELECT @@SQL_AUTO_IS_NULL')
   result = cursor.fetchone()
   return result and result['@@SQL_AUTO_IS_NULL'] == 1
 
 
class DatabaseWrapper(base.DatabaseWrapper):
 features_class = DatabaseFeatures
 
 def create_cursor(self, name=None):
  cursor = self.connection.cursor(self.Database.cursors.DictCursor)
  return base.CursorWrapper(cursor)
 
 @cached_property
 def mysql_server_info(self):
  with self.temporary_connection() as cursor:
   cursor.execute('SELECT VERSION()')
   return cursor.fetchone()['VERSION()']

最后在django项目的settings.py文件里修改数据库配置的数据库引擎

DATABASES = {
 'default': {
  'ENGINE': 'Test.mysql', # 指定数据库驱动为刚刚创建的mysql文件夹
  'NAME': 'test', # 指定的数据库名
  'USER': 'root', # 数据库登录的用户名
  'PASSWORD': '123456', # 登录数据库的密码
  'HOST': '127.0.0.1',
  'PORT': '3306', # 数据库服务器端口,mysql默认为3306
  'DATABASE_OPTIONS': {
   'connect_timeout': 60,
   'init_command': "SET sql_mode='STRICT_TRANS_TABLES'",
   'charset': 'utf8mb4',
  },
 }
}

测试

from django.db import connections
 
def f():
 search_sql = "SELECT propertyphotoid,propertyid,alykey FROM lansi_architecture_data.propertyphoto limit 0,5"
 cursor = connections['default'].cursor()
 try:
  cursor.execute(search_sql)
  rows = cursor.fetchall()
 except Exception as e:
  print(e)
  rows = 1
 
 print(rows)

输出结果

[{'propertyphotoid': 27, 'propertyid': 0, 'alykey': '123456'}, {'propertyphotoid': 28, 'propertyid': 10837, 'alykey': 'Property/6113/207504A1-AC65-4E3B-BE86-538B3807D364'}, {'propertyphotoid': 29, 'propertyid': 6113, 'alykey': 'Property/6113/357A4EAE-750A-4F59-AF01-271B4225CFBD'}, {'propertyphotoid': 31, 'propertyid': 6113, 'alykey': 'Property/6113/6DF1A2C1-F54C-4462-8363-619806A2F085'}, {'propertyphotoid': 36, 'propertyid': 6113, 'alykey': 'Property/6113/572CB245-ABC0-4FD6-8353-729EBD5E5D46'}]

源码解析:

django.db.utils.ConnectionHandler的__getitem__方法

django执行原始查询sql,并返回Dict字典例子

获取连接对象的游标是由DatabaseWrapper类的create_cursor返回的。所以只需要重写create_cursor方法,就可以更改游标返回的数据类型了。

django.db.backends.mysql.base.DatabaseWrapper类中的create_cursor方法如下:

def create_cursor(self, name=None):
  cursor = self.connection.cursor()
  return CursorWrapper(cursor)

到这里,理论上已经完成了重写目标,但是在测试的时候出错了,在django.db.backends.mysql.features.DatabaseFeatures里的is_sql_auto_is_null_enabled方法报出KeyError的错误。

@cached_property
 def is_sql_auto_is_null_enabled(self):
  with self.connection.cursor() as cursor:
   cursor.execute('SELECT @@SQL_AUTO_IS_NULL')
   result = cursor.fetchone()
   return result and result[0] == 1

原因是is_sql_auto_is_null_enabled方法使用了重写后的游标,cursor.execute('SELECT @@SQL_AUTO_IS_NULL')返回的结果不是元组,而是一个字典。所以result[0]会报出KeyError的错误。重写is_sql_auto_is_null_enabled方法把result[0]改成result['@@SQL_AUTO_IS_NULL']就可以了.

最后还需要把DatabaseWrapper类里的features_class赋值为重写后的DatabaseFeatures类。

以上这篇django执行原始查询sql,并返回Dict字典例子就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python3.0与2.X版本的区别实例分析
Aug 25 Python
跟老齐学Python之数据类型总结
Sep 24 Python
Python函数式编程指南(四):生成器详解
Jun 24 Python
基于Django的ModelForm组件(详解)
Dec 07 Python
如何使用Python的Requests包实现模拟登陆
Apr 27 Python
python邮件发送smtplib使用详解
Jun 16 Python
django获取from表单multiple-select的value和id的方法
Jul 19 Python
python读取与处理netcdf数据方式
Feb 14 Python
Python 窗体(tkinter)下拉列表框(Combobox)实例
Mar 04 Python
如何使用pandas读取txt文件中指定的列(有无标题)
Mar 05 Python
python smtplib发送多个email联系人的实现
Oct 09 Python
OpenCV绘制圆端矩形的示例代码
Aug 30 Python
python 日志 logging模块详细解析
Mar 31 #Python
django迁移文件migrations的实现
Mar 31 #Python
详解用Pytest+Allure生成漂亮的HTML图形化测试报告
Mar 31 #Python
浅谈Django中的QueryDict元素为数组的坑
Mar 31 #Python
Python + selenium + crontab实现每日定时自动打卡功能
Mar 31 #Python
python实现udp聊天窗口
Mar 31 #Python
浅谈在django中使用filter()(即对QuerySet操作)时踩的坑
Mar 31 #Python
You might like
php4的session功能评述(一)
2006/10/09 PHP
PHP新手上路(十一)
2006/10/09 PHP
PHPMyadmin 配置文件详解(配置)
2009/12/03 PHP
PHP合并数组+与array_merge的区别分析
2010/08/01 PHP
php强制文件下载而非在浏览器打开的自定义函数分享
2014/05/08 PHP
php中error与exception的区别及应用
2014/07/28 PHP
PHP程序员必须清楚的问题汇总
2014/12/18 PHP
smarty学习笔记之常见代码段用法总结
2016/03/19 PHP
PhpStorm terminal无法输入命令的解决方法
2016/10/09 PHP
php实现自定义中奖项数和概率的抽奖函数示例
2017/05/26 PHP
Javascript 表单之间的数据传递代码
2008/12/04 Javascript
动态调用CSS文件的JS代码
2010/07/29 Javascript
JS.getTextContent(element,preformatted)使用介绍
2013/09/21 Javascript
类似php的js数组的in_array函数自定义方法
2013/12/27 Javascript
Jquery下EasyUI组件中的DataGrid结果集清空方法
2014/01/06 Javascript
jQuery中outerWidth()方法用法实例
2015/01/19 Javascript
基于jquery实现在线选座订座之影院篇
2015/08/24 Javascript
JS碰撞运动实现方法详解
2016/12/15 Javascript
Angularjs中使用layDate日期控件示例
2017/01/11 Javascript
javascript获取以及设置光标位置
2017/02/16 Javascript
使用Node.js实现ORM的一种思路详解(图文)
2017/10/24 Javascript
微信小程序多音频播放进度条问题
2018/08/28 Javascript
详解Vue iview IE浏览器不兼容报错(Iview Bable polyfill)
2019/01/07 Javascript
js判断鼠标移入移出方向的方法
2020/06/24 Javascript
three.js着色器材质的内置变量示例详解
2020/08/16 Javascript
python实现K最近邻算法
2018/01/29 Python
python 重定向获取真实url的方法
2018/05/11 Python
Pycharm保存不能自动同步到远程服务器的解决方法
2019/06/27 Python
Python如何合并多个字典或映射
2020/07/24 Python
基于CSS3的CSS 多栏(Multi-column)实现瀑布流源码分享
2014/06/11 HTML / CSS
Glamest意大利:女性在线奢侈品零售店
2019/04/28 全球购物
照片礼物和装饰:MyPhoto
2019/11/02 全球购物
事业单位绩效考核实施方案
2014/03/27 职场文书
护士实习自荐信
2015/03/06 职场文书
幼儿园教师师德承诺书
2015/04/28 职场文书
Spring中bean的生命周期之getSingleton方法
2021/06/30 Java/Android