使用 Django ORM 对数据库进行修改时,Django 会自动调用 set_dirty() 。但如果你使用了原始 SQL ,Django 就无法获得你的 SQL 是否修改了数据。只有手动调用 set_dirty() 才能确保 Django 知晓哪些修改必须被提交。
执行原始 SQL 查询(Performing raw SQL queries)¶
你可以自由地在自定义的 model 方法和模块级(module-level)方法中使用原始 SQL 语句。 django.db.connection 对象表示当前数据库连接,而 django.db.transaction 表示当前数据库的事务。调用 connection.cursor() 会得到一个游标对象,可以用它来操作数据库。然后,调用 cursor.execute(sql, [params]) 执行 SQL ,然后调用 cursor.fetchone() 或 cursor.fetchall() 返回结果行。在执行了一个数据更改的操作之后,你应该调用 transaction.commit_unless_managed() 以确保数据改动被提交到数据库。如果你的操作仅仅是一个读取操作,那么没必要提交。例如:
def my_custom_sql(self):
from django.db import connection, transaction
cursor = connection.cursor()
# Data modifying operation - commit required
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
transaction.commit_unless_managed()
# Data retrieval operation - no commit required
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()
return row
事务和原始 SQL (Transactions and raw SQL)¶
如果你正在使用事务装饰器(例如 commit_on_success)来修饰视图和提供事务控制。你不必手动调用 transaction.commit_unless_managed(),当然如果你愿意的话,可以手动调用,但是一般情况下用不着这么做,这是因为装饰器会为你自动提交事务。但是,如果你不手动提交修改,你需要使用 transaction.set_dirty() 将事务标识为已脏
@commit_on_success
def my_custom_sql_view(request, value):
from django.db import connection, transaction
cursor = connection.cursor()
# Data modifying operation
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [value])
# Since we modified data, mark the transaction as dirty
transaction.set_dirty()
# Data retrieval operation. This doesn't dirty the transaction,
# so no call to set_dirty() is required.
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [value])
row = cursor.fetchone()
return render_to_response('template.html', {'row': row})
使用 Django ORM 对数据库进行修改时,Django 会自动调用 set_dirty() 。但如果你使用了原始 SQL ,Django 就无法获得你的 SQL 是否修改了数据。只有手动调用 set_dirty() 才能确保 Django 知晓哪些修改必须被提交。
连接和游标(Connections and cursors)¶
连接(connection) 和 游标(cursor) 实现了大部分标准的 Python DB-API (除了 事务处理(transaction handling) 之外)。 如果你并不熟悉 Python DB-API,建议您 cursor.execute() 中的 SQL 语句使用 "%s" 占位符,而不是直接在 SQL 中添参数。如果你使用了占位符,幕后的数据库类库将自动添加引号,并对参数中的某些字符进行转义(要注意 Django 使用 "%s" 占位符,而不是 "?" 占位符--为 Python 中的 SQLite 库所用,这样做是为了使用方便和用法一致。)