[转](20条消息) Django数据库操作(执行原生SQL的几种方法)

本文介绍了Django中如何使用extra()方法进行额外查询参数设置,通过select()方法选择额外字段,以及raw()方法执行原始SQL查询。同时涵盖了自定义SQL执行,包括使用游标进行插入、更新、删除和查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.使用extra方法

解释:结果集修改器,一种提供额外查询参数的机制

说明:依赖model模型

用在where后:

Book.objects.filter(publisher_id=“1”).extra(where=[“title=‘python学习1’”])

用在select后

Book.objects.filter(publisher_id=“1”).extra(select={“count”:“select count(*) from hello_book”})

2.使用raw方法

解释:执行原始sql并返回模型

说明:依赖model多用于查询

用法:

book = Book.objects.raw(“select * from hello_book”)
    for item in book:
      print(item.title)

3.执行自定义SQL

解释:利用游标执行

导入:from django.db import connection

说明:不依赖model

用法:

from django.db import connection

cursor = connection.cursor()
    #插入
    cursor.execute(“insert into hello_author(name) values(‘xiaol’)”)
    #更新
    cursor.execute(“update hello_author set name=‘xiaol’ where id=1”)
    #删除
    cursor.execute(“delete from hello_author where name=‘xiaol’”)
    #查询
    cursor.execute(“select * from hello_author”)
    #返回一行
    raw = cursor.fetchone()
    print(raw)
    # #返回所有
    # cursor.fetchall()

---------------------
作者:icy城市稻草人
来源:优快云
原文:https://blog.youkuaiyun.com/hegui1997/article/details/89398511
版权声明:本文为作者原创文章,转载请附上博文链接!

<think>好的,我现在需要在Django 2.25中执行原生SQL查询。首先,我应该回忆一下Django的文档里关于数据库访问的部分。记得Django ORM通常处理大多数查询,但有时候直接执行SQL会更高效或更灵活。用户提到的是Django 2.25,所以得确保方法适用于这个版本,不会因为版本差异出现问题。 首先,Django提供了几种执行原生SQL的方式。一个是使用Manager.raw()方法,另一个是直接使用数据库连接执行自定义SQL。这两种方法有什么区别呢?raw()方法用于执行SELECT查询并返回模型实例,而直接执行可能用于其他操作如INSERT、UPDATE等。此外,还有可能需要处理事务,特别是当执行写操作时,需要确保原子性,像用户提供的例子中使用了事务。 接下来,我需要分步骤说明如何在Django执行这两种类型的查询。对于读取操作,使用raw()方法可能更合适,因为它可以将结果映射到模型实例。例如,假设有一个Person模型,可以用Person.objects.raw('SELECT * FROM myapp_person')来获取数据。需要注意SQL注入的问题,所以应该避免拼接用户输入的参数,而是使用参数化查询,比如使用raw()的params参数。 对于需要执行更复杂的SQL,或者非SELECT操作,比如UPDATE或DELETE,可能需要使用django.db.connection。通过获取游标,然后执行execute()方法。这里同样要注意使用参数化查询,防止SQL注入。例如,cursor.execute("UPDATE ... WHERE id = %s", [user_id]),使用%s作为占位符,即使数据库不同,Django也会自动处理。 事务管理也是一个重点。用户提供的例子中用了transaction.atomic()来确保原子性,所以在执行多个数据库操作时,尤其是写操作,应该将代码放在事务块中。这一点需要提醒用户注意,特别是在执行原生SQL时,事务管理可能需要手动处理,或者利用Django的装饰器、上下文管理器。 另外,用户提到的是Django 2.25,而引用中的示例使用了F表达式和事务,这可能和评论功能相关,但执行原生SQL的上下文可能不同。需要确保给出的代码示例适用于该版本,并且没有使用过时的API。比如,在Django 2.x中,数据库连接的使用方式是否有变化?查阅文档确认,使用connection.cursor()仍然有效,且推荐使用上下文管理器来管理游标,比如with connection.cursor() as cursor:,这样可以自动关闭游标。 最后,注意事项部分需要涵盖SQL注入的风险,提醒用户永远不要直接将用户输入拼接到SQL语句中。另外,提及使用原生SQL可能带来的兼容性问题,比如不同的数据库后端可能有不同的SQL方言,导致代码难以移植。同时,性能方面,虽然有时候原生SQL更快,但ORM通常已经优化得很好,所以建议在必要时才使用原生查询。 生成相关问题的时候,需要考虑用户可能的后续问题,比如事务处理、参数化查询的具体写法、如何获取查询结果,以及调试原生SQL方法等。这些问题应该覆盖用户在使用原生SQL时可能遇到的常见挑战,帮助他们更全面地理解和应用所学内容。</think>### 如何在 Django 2.25 中执行原生 SQL 查询 在 Django 2.25 中执行原生 SQL 查询主要通过以下两种方式实现,需根据场景选择合适的方法: --- #### 1. **使用 `raw()` 方法(适用于 SELECT 查询)** `raw()` 方法可将查询结果映射到模型实例,适合需要直接操作模型对象的场景。 **语法示例:** ```python from myapp.models import Person # 基本查询 persons = Person.objects.raw('SELECT * FROM myapp_person WHERE age > %s', [20]) # 带参数的查询(防止 SQL 注入) query = 'SELECT * FROM myapp_person WHERE name LIKE %s' results = Person.objects.raw(query, ['%张%']) # 遍历结果 for person in results: print(person.name) ``` **注意事项:** - 必须指定表名(如 `myapp_person`),与数据库中的实际表名一致。 - 使用 `%s` 作为占位符,参数通过列表传递[^1]。 --- #### 2. **直接使用数据库连接(适用于任意 SQL 语句)** 通过 `django.db.connection` 获取游标执行任意 SQL 语句,适合非 SELECT 操作或复杂查询。 **语法示例:** ```python from django.db import connection def update_user_email(user_id, new_email): with connection.cursor() as cursor: # 执行 UPDATE 语句 cursor.execute(""" UPDATE myapp_user SET email = %s WHERE id = %s """, [new_email, user_id]) # 执行 SELECT 查询并获取结果 cursor.execute("SELECT COUNT(*) FROM myapp_user") row = cursor.fetchone() print(row[0]) ``` **事务管理(确保原子性):** ```python from django.db import transaction with transaction.atomic(): # 事务块 with connection.cursor() as cursor: cursor.execute("INSERT INTO myapp_log (message) VALUES (%s)", ['操作日志']) cursor.execute("UPDATE myapp_stats SET count = count + 1") ``` --- ### **注意事项** 1. **SQL 注入风险** 始终使用参数化查询(`%s` 占位符),避免直接拼接字符串。例如: ```python # 错误方式(风险高) cursor.execute(f"SELECT * FROM table WHERE name = '{user_input}'") # 正确方式(安全) cursor.execute("SELECT * FROM table WHERE name = %s", [user_input]) ``` 2. **跨数据库兼容性** 原生 SQL 可能依赖特定数据库语法(如 PostgreSQL 的 `ILIKE`),需注意移植性。 3. **性能权衡** ORM 已针对常见场景优化,仅在复杂查询或性能瓶颈时使用原生 SQL。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值