1. 程式人生 > >Django中直接執行SQL語句

Django中直接執行SQL語句

歡迎加入python學習交流群 667279387

今天在django views.py看到同事寫的程式碼裡面有段關於資料庫查詢的語句。因為涉及多個表的查詢,所以django 的models的查詢無法滿足需求,所以直接執行了SQL語句。他是按照下面的方法實現的。

    try:
        connection = MySQLdb.connect(host=SQL_IP,
                                     user=SQL_USER,
                                     passwd=SQL_PASSWD,
                                     db=SQL_DB, charset='utf8')
cursor = connection.cursor() cmd_query = query_data(request) data_sort = sort_data(request) cmd = "set session group_concat_max_len = 8000;" cursor.execute(cmd) ......

看到這段程式碼,感覺應該重複造了輪子,資料庫的連結應該交由django這個框架處理的。於是查看了下官方文件。
django.db.connection 就是上面的同事寫的那個connection了。
後面的方法同他的一樣執行就是了。即執行
connection.cursor()
cursor.execute(sql, [params])
cursor.fetchone() or cursor.fetchall()
下面是一個簡單的例子。

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

如果你專案中有多個數據庫的話,django.db.connection也能很方便的選取資料庫。django.db.connections 是一個類字典的結構,允許你使用資料庫別名獲取connection。

from django.db import connections
with connections['my_db_alias'].cursor() as cursor:
    # Your code here...

使用with作為上下文管理器:

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

和下面這段程式碼等效

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

注意的問題:
如果你做了更新或者插入操作需要在程式碼中使用 :transaction.commit_unless_managed() 來提交資料。或者使用事務裝飾器(例如 commit_on_success)來修飾檢視和提供事務控制資料提交。這樣就不用在程式碼中呼叫transaction.commit_unless_managed()。但是,如果你不手動提交修改,你需要使用 transaction.set_dirty() 將事務標識為已髒。使用 Django ORM 對資料庫進行修改時,Django 會自動呼叫 set_dirty() 。但如果你使用了原始 SQL ,Django 就無法獲得你的 SQL 是否修改了資料。只有手動呼叫 set_dirty() 才能確保 Django 知曉哪些修改必須被提交。

from django.db.transaction import commit_on_success



@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()
    #transaction.commit_unless_managed()

    return render_to_response('template.html', {'row': row})

如果不使用

歡迎加入python學習交流群 667279387