django公式ドキュメント-元のsqlクエリーを実行


元のSQLクエリの実行
モデルクエリーAPIがまだ足りないと思ったら、元のSQLを使用できます.Djangoでは、元のSQLを実行する方法は2つあります.Managerを使用することができます.raw()は、元のクエリーを実行してモデルインスタンスを返すか、モデルレイヤを完全に避けてカスタムSQLを直接実行できます.
元のクエリの実行
New in Django 1.2:
Please, see the release notes
マネージャのraw()メソッドは、元のSQLを実行し、モデルインスタンスを返すために使用できます.
Manager. raw(
raw_query,
params=None,
translations=None) ¶
このメソッドは、元のSQLクエリを実行し、RawQuerySetインスタンスを返します.このRawQuerySetインスタンスは反復可能であり、通常のクエリーセットのようにオブジェクトインスタンスを提供することができる.
例を挙げると分かりやすいです.次のモデルがあるとします.
class Person(models.Model):
    first_name = models.CharField(...)
    last_name = models.CharField(...)
    birth_date = models.DateField(...)

このようにカスタムSQLを実行できます
>>> for p in Person.objects.raw('SELECT * FROM myapp_person'):
...     print p
John Smith
Jane Jones

もちろんこの例は面白くないが、Personを実行したに相当する.objects.all() .しかし、raw()には相当な力のパラメータがたくさんあります.
モデルテーブル名
前例のPersonテーブルの名前は何ですか?
デフォルトでは、Djangoはモデルの「適用ラベル」(manage.py startappで使用する名前)とモデルのクラス名を下線で接続してデータベーステーブル名とします.前例では、Personモデルがmyappという名前のアプリケーションにあると仮定していますので、テーブル名はmyapp_personです.
詳細はdb_を参照Tableオプションのドキュメント.このオプションでは、データベース・テーブル名を手動で指定することもできます.
Warning
渡すraw()のSQL文はDjangoで検証されません.Djangoは、データベースからローのセットを返すことを期待しますが、これは強制的ではありません.クエリがローを返さない場合は、(暗黙的な)エラーが発生します.
クエリーフィールドをモデルフィールドにマップする.
raw()は、クエリーのフィールドをモデルフィールドに自動的にマッピングします.
クエリー内のフィールドの順序はどうでもいいです.つまり、次の2つの言葉は同じです.
>>> Person.objects.raw('SELECT id, first_name, last_name, birth_date FROM myapp_person')
...
>>> Person.objects.raw('SELECT last_name, birth_date, first_name, id FROM myapp_person')
...

マッピングは名前に基づいて行われます.SQLのAS句を使用してマッピングできます.したがって、Personデータを含む他のテーブルがあれば、Personインスタンスに簡単にマッピングできます.
>>> Person.objects.raw('''SELECT first AS first_name,
...                              last AS last_name,
...                              bd AS birth_date,
...                              pk as id,
...                       FROM some_other_table''')

名前が一致すると、モデルインスタンスが正しく作成されます.
raw()のtranslationsパラメータを使用してマッピングする方法もあります.このパラメータは、クエリーフィールド名とモデルフィールド名をマッピングする辞書です.上記のクエリは、次のように書くこともできます.
>>> name_map = {'first': 'first_name', 'last': 'last_name', 'bd': 'birth_date', 'pk': 'id'}
>>> Person.objects.raw('SELECT * FROM some_other_table', translations=name_map)

索引検索
raw()はインデックスをサポートしているので、最初の結果だけが必要な場合は、次のようにします.
>>> first_person = Person.objects.raw('SELECT * from myapp_person')[0]

ただし、インデックスとスライスはデータベース・レベルでは実行されません.データベースにPersonオブジェクトが多数存在する場合は、SQLレベルでクエリの効率性を制限します.
>>> first_person = Person.objects.raw('SELECT * from myapp_person LIMIT 1')[0]

遅延モデルフィールド
フィールドは不完全でもかまいません.
>>> people = Person.objects.raw('SELECT id, first_name FROM myapp_person')

この例でクエリが返すPersonオブジェクトは、遅延モデルインスタンスになります(defer()を参照).つまり、クエリーで省略されたフィールドは、必要に応じてロードされます.例:
>>> for p in Person.objects.raw('SELECT id, first_name FROM myapp_person'):
...     print p.first_name, # This will be retrieved by the original query
...     print p.last_name # This will be retrieved on demand
...
John Smith
Jane Jones

表面的には、名前と姓を同時に取得したようです.しかし,この例では実際に3つのクエリが発行されている.元のクエリは名前のみが取得され、2つの姓は印刷時にそれぞれ取得されます.
省略できない唯一のフィールドはプライマリ・キーです.Djangoは、モデルインスタンスを判別するためにプライマリ・キーを使用するため、元のクエリにプライマリ・キーを含める必要があります.そうしないと、InvalidQuery例外が放出されます.
統計に加わる.
モデルにないフィールドを含むクエリーも実行できます.たとえば、PostgreSQLのage()関数を使用して、データベースにユーザの年齢を統計できます.
>>> people = Person.objects.raw('SELECT *, age(birth_date) AS age FROM myapp_person')
>>> for p in people:
...     print "%s is %s." % (p.first_name, p.age)
John is 37.
Jane is 42.
...

パラメータをraw()に渡す.
パラメータ付きクエリーを実行する必要がある場合は、paramsパラメータを使用します.
>>> lname = 'Doe'
>>> Person.objects.raw('SELECT * FROM myapp_person WHERE last_name = %s', [lname])

paramsはパラメータリストです.クエリー文字列で%sプレースホルダを使用します(データベース・エンジンに関係なく).プレースホルダはparamsリストのパラメータに置き換えられます.
Warning
元のクエリでフォーマット文字列を使用しないでください.
上記のクエリを次のように書くことができます.
>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
>>> Person.objects.raw(query)

決してそんなことをしてはいけない.
paramsリストを使用すると、SQL注入攻撃から保護できます(脆弱性を通じて悪意のあるSQLをデータベースに注入します).文字列挿入を使用すると、できるだけ早くSQL注入の被害者になりますので、paramsリストを使用することを忘れないでください.
カスタムSQLを直接実行する.
時々、Manager.raw()はまだ十分ではありません.対応するモデルが不明なクエリーを実行するか、UPDATE、INSERT、DELETEクエリーを直接実行する必要があります.
この場合、データベースを直接操作して、モデルレイヤを完全に迂回することができます.
django.db.接続オブジェクトはデフォルトのデータベース接続、djangoを表す.db.Transactionはデフォルトのデータベーストランザクションを表します.データベース接続を使用してconnectionを呼び出すには.cursor()を使用してポインタオブジェクトを取得します.次にcursorを呼び出すことができます.Excute(sql,[params])はSQLとcursorを実行する.fetchone()またはcursor.fetchall()は、結果行を返します.データを変更する操作を実行した後、transactionを呼び出す必要があります.commit_unless_managed()は、あなたの変更が提出されることを確認します.データを取得するだけならコミットする必要はありません.例:
def my_custom_sql():
    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

複数のデータベースを使用する場合はdjangoを使用します.db.connectionsは、指定したデータベースの接続(およびポインタ)を取得します.django.db.connectionsは、指定したデータベースの接続を別名で取得できる辞書のようなオブジェクトです.
from django.db import connections
cursor = connections['my_db_alias'].cursor()
# Your code here...
transaction.commit_unless_managed(using='my_db_alias')

トランザクションと元のSQL
元のSQLを実行すると、Djangoは自動的に現在のトランザクションをブラックボックスに入れます.事務が正しく終わることを確認しなければなりません.詳細はDjangoのトランザクション要件の注意点を参照してください.
Changed in Django Development version.
Django 1.3版の前に、元のSQLを使用する場合はtransactionを通過する必要があります.set_dirty()手動でトランザクションをブラックボックスに入れます.
接続とポインタ.
接続とポインタのほとんどは、トランザクションのためでない限り、標準Python DB-APIを実行します.Python DB-APIに詳しくない場合は、cursor.execute()のSQL文は、SQLに直接パラメータを追加するよりもプレースホルダ「%s」を使用することに注意してください.このテクノロジーを使用すると、ベース・データベースは必要に応じてパラメータに引用符とエスケープを自動的に追加します.このようにするのは一致性の原則に合致し、賢いやり方である.(Djangoは「%s」ではなくプレースホルダとして使用することにも注意してください.)