| revision-up-to: | 11321 (1.1) unfinished |
|---|
自作のモデルメソッドやモジュールレベルのメソッドでは、自由にカスタムの SQL 文を書けます。 django.db.connection というオブジェクトが現在のデータベー ス接続を表現しています。カスタムSQL を使うには、まず connection.cursor() を呼び出してカーソルオブジェクトを取得し、次いで cursor.execute(sql, [params]) を呼び出して SQL を実行した後、 cursor.fetchone() や cursor.fetchall() を読んで結果行を返します。 データを変更する操作を行った後には、必ず transaction.commit_unless_managed() を呼び出して、変更をデータベースに commit してください。クエリが単にデータを取得するだけの操作なら、 commit は 必要ありません。
例を示しましょう:
def my_custom_sql(self):
from django.db import connection, transaction
cursor = connection.cursor()
# データを変更する操作なので、 commit が必要
cursor.execute("UPDATE bar SET foo = 1 WHERE baz = %s", [self.baz])
transaction.commit_unless_managed()
# データを取得するだけの操作なので commit は不要
cursor.execute("SELECT foo FROM bar WHERE baz = %s", [self.baz])
row = cursor.fetchone()
return row
If you are using transaction decorators (such as commit_on_success) to wrap your views and provide transaction control, you don't have to make a manual call to transaction.commit_unless_managed() -- you can manually commit if you want to, but you aren't required to, since the decorator will commit for you. However, if you don't manually commit your changes, you will need to manually mark the transaction as dirty, using 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})
The call to set_dirty() is made automatically when you use the Django ORM to make data modifying database calls. However, when you use raw SQL, Django has no way of knowing if your SQL modifies data or not. The manual call to set_dirty() ensures that Django knows that there are modifications that must be committed.
connection や cursor は標準の Python DB-API が提供する機能の (トランザクションの扱い を除いた) ほとんど を実装しています。 Python DB-API に詳しくないのなら、上の SQL 文の cursor.execute() でパラメタを直接 SQL に入れるのではなく、プレースホル ダ "%s" を使っていることに注意して下さい。このテクニックを使うと、根底 にあるデータベースライブラリは必要に応じて自動的にパラメタをクオートしたり エスケープ処理したりします。 (また、Django はプレースホルダ文字として SQLite の Python バインディングが使っている "?" ではなく "%s" を使うので注意してください。これはインタフェースに一貫性をもたせるための設 計です。)
注意: WHERE 節を自分で設定したいだけなら、標準の照合 API に where や tables 、 params といった引数を指定して実現できます。
Aug 19, 2010