Django 使用 raw sql


connections與connection

db.connections是一個類似字典的對象,可以通過某個數據庫連接的別名獲取這個數據源的connection。比如connections['my_db_alias']

from django.db import connections
for key in connections:
    print(key)
# 可以打印出所有配置了的數據源別名,django會為每個數據源創建一個connection

通過django/db/init.py中

class DefaultConnectionProxy:
    """
    Proxy for accessing the default DatabaseWrapper object's attributes. If you
    need to access the DatabaseWrapper object itself, use
    connections[DEFAULT_DB_ALIAS] instead.
    """
    def __getattr__(self, item):
        return getattr(connections[DEFAULT_DB_ALIAS], item)

    def __setattr__(self, name, value):
        return setattr(connections[DEFAULT_DB_ALIAS], name, value)

    def __delattr__(self, name):
        return delattr(connections[DEFAULT_DB_ALIAS], name)

    def __eq__(self, other):
        return connections[DEFAULT_DB_ALIAS] == other


connection = DefaultConnectionProxy()

由於DEFAULT_DB_ALIAS='default',可以知道from django.db import connection獲取的就是connections['default']

因此,在多數據庫的情況下,可以通過connections獲取特定數據庫連接的queries或cursor

from django.db import connections
connections['my_db_alias'].queries
cursor = connections['my_db_alias'].cursor()

使用cursor跨庫查詢

前面已經提到,使用connection.cursor()表示使用默認數據庫的連接

如果有多個數據庫連接配置,那么一定要用connections[db_name].cursor()指定一個

那么在connections[db_name].cursor()中可以查到另一個schema中的表嗎?

答案是可以的

比如,我想要連接db_1的order表和db_2的product表,可以使用connections[db_1].cursor()進行連接,然后在sql中通過db_2.product訪問db_2

sql = "select o.id from order o, db_2.product p where o.product_id=p.id and p.type=%s"
sql_values = [1]
with connections["db_1"].cursor() as cur:
    cur.execute(sql, sql_values)
    order_ids = [row[0] for row in cur.fetchall()]

前提是db_2與db_1在同一個MySQL的服務端上

傳遞cursor參數

cur.execute(sql, sql_values) 並不是簡單的字符串拼接,它可以有效防止sql注入

注意以下的寫法是錯誤的

# 直接使用字符串拼接
>>> query = 'SELECT * FROM myapp_person WHERE last_name = %s' % lname
>>> Person.objects.raw(query)

# 畫蛇添足地使用'%s',不需要擔心cursor識別不了字符串
>>> query = "SELECT * FROM myapp_person WHERE last_name = '%s'"

占位符對應的python數據類型可以是int、str、datetime、list等類型。這些類型在被整合進sql語句前都會得到正確的處理

sql = (
		"select * from product where "
   "created_time >= %s and type in %s and order_id = %s and device_name = %s"
)
cursor.execute(sql, [datetime.now(), [1,2], 123, "iphone"])

參考文檔

https://docs.djangoproject.com/en/3.1/topics/db/sql/


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM