Django笔记之使用原生SQL查询数据库

news2024/12/23 1:38:42

Django 提供了两种方式来执行原生 SQL 代码。

一种是使用 raw() 函数,一种是 使用 connection.cursor()。

但是官方还是推荐在使用原生 SQL 之前,尽量的先去探索一下 QuerySet 提供的各种 API。

目前而言,官方文档提供的各种 API 是能够满足绝大多数的应用场景的。

 

以下是本篇笔记的目录:

  1. raw()
  2. connection.cursor()
  3. 多数据库操作

1、raw()

这个方法可以用来操作原生 SQL,然后返回 model 实例:

我们以 Blog 作为示例,使用的代码如下:

for blog in Blog.objects.raw("select * from blog_blog"):
    print(blog)

上面这段代码的作用效果跟 Blog.objects.all() 获取的结果是一样的,但是在一些操作上又不太一样,比如 all().count() 可以获取到 总数,但是 raw() 就不能进行这种操作。

需要注意的是,raw() 并不会去检测输入的 SQL 代码,即使我们使用 Blog 这个model 来查询 Entry 的数据,也能够返回结果,不过返回的都是 Entry 表的属性:

for blog in Blog.objects.raw("select * from blog_entry"):
    print(blog.__dict__)  # __dict__ 输出的都是 blog_entry 的字段

也就是说 在 Blog.objects.raw() 中,真正起作用的只有 raw() 这一个函数,前面的 Blog 不过是一个架子,或者途径,是为了引出 raw() 这个函数。

自定义返回字段

在 raw() 函数的 SQL 代码里,我们可以自定义选中的字段,如果需要使用没有选中的字段,那么系统会再次访问数据库来获取,这个操作过程就跟前面介绍的 defer() 函数一样。

for item in Blog.objects.raw("select id from blog_blog"):
    print(item.__dict__)
    print(item.id, item.name)
    print(item.__dict__)

{'_state': <django.db.models.base.ModelState object at 0x7fbd4165b6a0>, 'id': 2}
2 hunter
{'_state': <django.db.models.base.ModelState object at 0x7fbd4165b6a0>, 'id': 2, 'name': 'hunter'}

可以看到,返回的结果中先输出的数据只有 id,后面,当我们访问 name 字段的时候,又去获取了 name 字段的数据。

自定义字段必须包含主键

当我们自定义字段返回的时候,必须是要包含主键字段的,否则在我们获取信息的时候会报错,比如下面的操作:

for blog in Blog.objects.raw("select name from blog_blog"):
    print(blog.__dict__)

在 print(blog.dict) 的时候就会报错,数据中没有主键信息

自定义返回新字段

可以跟 QuerySet 的 annotate 操作一样,自定义新字段返回,获取的时候可以直接根据属性值返回,比如:

entry = Entry.objects.raw("select *, date_format(pub_date, '%%Y-%%m') as date_1 from blog_entry")[0]
print(entry.date_1)

传递变量

给输入的 SQL 语句传递变量:

name = "python"
Blog.objects.raw("select * from blog_blog where name = '%s'", [name])

2、connection.cursor()

Django 推出了一种更加直接执行 SQL 的方式,用到的模块是 django.db.connction,用到的 cursor 和 pymysql 的库是一样的用法,官方给出的示例如下:

from django.db import connection


def my_custom_sql(self):
    with connection.cursor() as cursor:
        cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
        cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
        row = cursor.fetchone()

    return row

需要注意,如果有参数传入 SQL 中,需要对一些符号进行转义之后才可以使用,比如:

cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' AND id = %s", [self.id])

其中,第二条语句的 % 需要进行转义

适配fetch的数据

通过 fetchone 和 fetchall() 返回的数据是只有 value 值的,没有对应的字段 key,如果可以适当的牺牲性能和内存,来换取获取数据的便利和准确性,官方提供了这样一种方式:

def dictfetchall(cursor):
    "Return all rows from a cursor as a dict"
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]

在我们执行完 cursor.execute(sql) 之后,把 cursor 作为参数传入 dictfetchall 函数中,就可以返回一个字典列表

介绍一下 cursor.description,这个返回的是一个元组数据,里面的元素也是一个元组,元组的第一个元素就是我们 select 的字段名。

所以 columns = [col[0] for col in cursor.description] 这一行代码获取的是指定的所有字段名

使用示例:

def dictfetchall(cursor):
    "Return all rows from a cursor as a dict"
    columns = [col[0] for col in cursor.description]
    return [
        dict(zip(columns, row))
        for row in cursor.fetchall()
    ]

with connection.cursor() as cursor:
	sql = "select id, name from blog_blog"
	cursor.execute(sql)
	results = dictfetchall(cursor)

print(results)

# 返回的结果:
# [{'id': 20, 'name': 'name_3'}, {'id': 21, 'name': 'name_4'}, {'id': 1, 'name': 'name_5'}]

在我使用的过程中,我们使用的是上下文管理器的方式来获取游标:

with connection.cursor() as cursor:
	cursor.execute()

所以,使用完之后,不需要手动关闭,他与下面的用法效果是一致的:

c = connection.cursor()
try:
    c.execute(...)
finally:
    c.close()

但推荐的还是上下文管理器的方式,更优雅。

3、多数据库操作

如果系统用到了多个数据库,那么在使用 cursor 的时候,就需要使用到 django.db.connections 模块:

from django.db import connections
with connections['my_db_alias'].cursor() as cursor:
    pass

以上就是本篇笔记全部内容,下一篇笔记将简单介绍一下多数据库的操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/825441.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

修改cuda软链接(实操演示)

文章目录 1 找到已存在的CUDA软链接2 确认当前软链接真实路径3 删除现有软链接4 创建新的软链接5 验证新的软链接 要修改CUDA的软链接&#xff0c;需要找到已经存在的软链接并重新创建它指向新的目录。 1 找到已存在的CUDA软链接 首先&#xff0c;需要找到之前创建的CUDA软链…

编程:必备技能还是浪费时间?

当下&#xff0c;学习编程正变得越来越受欢迎&#xff0c;许多人都在探讨这个话题&#xff0c;但仍有很多人产生疑问&#xff1a;学习编程是否有必要&#xff1f;我们可以从学习编程的好处和应用领域来进行分析。好处方面&#xff0c;乔布斯曾说&#xff1a;“人人都应该学习编…

安装企业级高负载web服务器tomcat,并部署应用

web服务器Tocamt 1.Tocmat简介2.Tocmat安装1.安装jdk2.部署Tomcat1.配置环境变量2.启动tocmat3.Tomcat web管理功能 3.部署jpress应用 1.Tocmat简介 Tomcat是Apache软件基金会&#xff08;Apache Software Foundation&#xff09;的Jakarta 项目中的一个核心项目&#xff0c;由…

【小白篇】Vscode配置Python和C++环境

文章目录 一、配置python环境二、配置C环境2.1 安装MinGW编译器2.2 安装C/C扩展2.3 配置C/C环境&#xff08;1&#xff09;配置编译器&#xff08;2&#xff09;配置构建任务&#xff08;3&#xff09;配置调试设置 2.4 测试例子2.5 注意事项 三、插件Reference 一、配置python…

MongoDB文档--基本概念

阿丹&#xff1a; 不断拓展自己的技术栈&#xff0c;不断学习新技术。 基本概念 MongoDB中文手册|官方文档中文版 - MongoDB-CN-Manual mongdb是文档数据库 MongoDB中的记录是一个文档&#xff0c;它是由字段和值对组成的数据结构。MongoDB文档类似于JSON对象。字段的值可以包…

网络安全【黑客技术】自学

1.网络安全是什么 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 2.网络安全市场 一、是市场需求量高&#xff1b; 二、则是发展相对成…

windows mysql5.7 开启binlog

查看binlog是否开启 show variables like %log_bin%; 找到安装目录的mysql配置文件 my.ini 编辑 my.ini文件 log-bin D:\Program Files\mysql\logs\log-bin binlog_format ROW server_id 2 按照 log-bin D:\Program Files\mysql\logs\log-bin 创建文件 重启mysql服务 重启…

医疗知识图谱问答 —— 数据同步

前言 前面的文章已经介绍了 neo4j 服务的本地安装&#xff0c;以及数据的增删改查操作方法。那么这里就要进入 python 项目&#xff0c;来完成医疗知识的构建&#xff0c;问答机器人的代码实现。但篇幅较长&#xff0c;本文就主要介绍知识图谱的构建吧。 环境 Anaconda3 Pyth…

外贸国际企业邮箱选择指南:哪家提供更优质的服务?

在当今的数字时代&#xff0c;跨国企业需要与世界各地的客户和合作伙伴保持联系。这就是为什么选择适合其全球运营的功能的正确的业务邮箱是至关重要的。 国际企业邮箱最受欢迎的选择是专门为外贸设计的邮箱服务。它们提供了一系列工具&#xff0c;如国际域名和自动语言翻译&am…

用代码获取每天热点内容信息,并发送到自己的邮箱

前言 大家早好、午好、晚好吖 ❤ ~欢迎光临本文章 本篇文章内容主要为如何用代码&#xff0c;把你想要的内容&#xff0c;以邮件的形式发送出去 内容可以自己完善&#xff0c;还可以设置一个定时发送&#xff0c;或者开机启动自动运行代码 开发环境: python 3.8 运行代码 p…

python算法指南程序员经典,python算法教程pdf百度云

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;你也能看懂的python算法书 pdf&#xff0c;python算法教程这本书怎么样&#xff0c;现在让我们一起来看看吧&#xff01; 给大家带来的一篇关于算法相关的电子书资源&#xff0c;介绍了关于算法、详解、算法基础方面的内…

无涯教程-Lua - 面向对象

面向对象编程(OOP)是现代编程时代中使用最广泛的编程技术之一。 OOP的特征 类(Class) - 类是用于创建对象的可扩展模板。 对象(Objects) - 它是类的实例&#xff0c;并为其分配了单独的内存空间。 继承(Inheritance) - 这是一个概…

操作系统第二章——进程与线程(圆满)

欲渡黄河冰塞川&#xff0c;将登太行雪满山 文章目录 2.3.7 生产者消费者问题能否改变相邻的PV操作的顺序知识回顾 2.3.8 多生产者多消费者问题问题描述关系分析各个进程之间的PV操作设置信号量若是不设置互斥信号量缓冲区大于一知识回顾 2.3.9 吸烟者问题知识回顾2.3.10读者写…

leetcod——62不同路径 (动态规划讲解)

62. 不同路径 中等 1.8K 相关企业 一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有…

五、JVM-垃圾回收算法

常见的回收算法&#xff1a;标记清除算法、复制算法、标记-整理算法、分代收集算法 1、标记清除算法 第一步&#xff1a;标记&#xff08;找出内存中需要回收的对象&#xff0c;并且把它们标记出来&#xff09; 第二步&#xff1a;清除 &#xff08;清除掉被标记需要回收的对…

【算法提高:动态规划】1.5 状态压缩DP TODO

文章目录 状态压缩DP例题列表棋盘式1064. 小国王⭐&#x1f402;&#xff08;好题&#xff01;&#xff09;做题套路总结 327. 玉米田&#xff08;好题&#xff01;&#x1f402; 和1064. 小国王差不多的题目&#xff09;292. 炮兵阵地&#xff08;和上面两道题差不多&#xff…

股票量化系统QTYX选股框架实战案例集|地产看前排承接做后排补涨,砸涨停板吃8点小肉-230801...

前言 “实战案例个股画像”系列和大家分享我基于QTYX选股框架&#xff0c;在实战中选股的案例&#xff0c;和大家一起见证QTYX选股框架逐步完善的过程&#xff0c;帮助大家理解QTYX的精髓。 关于QTYX的使用攻略可以查看链接&#xff1a;QTYX使用攻略 关于QTYX初衷和精髓可以查看…

CSS图片放到<div>里面,自适应宽高全部显示,点击图片跳到新页面预览,点击旋转按钮图片可旋转

有一个需求是图片放到一个固定宽高的<div>里面&#xff0c;不管是横图还是竖图&#xff0c;都要全部显示出来并且保持图片的长宽比例不变形&#xff0c;点击图片可以跳到一个新页面预览&#xff0c;代码如下&#xff1a; <!DOCTYPE html> <html> <head>…

图解系列 DNS查找过程和DNS缓存

DNS 充当地址簿。它将人类可读的域名 (google.com) 转换为机器可读的 IP 地址 (142.251.46.238)。 开局一张图 来自&#xff1a;https://xiaolishen.medium.com/the-dns-lookup-journey-240e9a5d345c 寻址流程 查询浏览器缓存&#xff1a;当你输入一个域名后&#xff0c;浏览…