使用Flask,我很想知道SQLAlchemy是否仍然是使用原始SQL(直接SELECT x FROM table WHERE ...
)查詢我的數據庫而不是使用ORM或者是否有更簡單但功能強大的替代方法的最佳方法?如果僅用於原始sql查詢,SQLAlchemy仍然是推薦的嗎?
感謝您的回覆。
使用Flask,我很想知道SQLAlchemy是否仍然是使用原始SQL(直接SELECT x FROM table WHERE ...
)查詢我的數據庫而不是使用ORM或者是否有更簡單但功能強大的替代方法的最佳方法?如果僅用於原始sql查詢,SQLAlchemy仍然是推薦的嗎?
感謝您的回覆。
我一直使用SQLAlchemy進行直接查詢。
主要優點:它爲您提供最佳的防範SQL注入攻擊。 SQLAlchemy不管你輸入什麼參數都會做正確的事情。
我發現它也可以根據條件調整生成的SQL。顯示上面有多個過濾器控件的結果集?只需在一組if/elif/else結構中構建你的查詢,你就知道你的SQL仍然是黃金。
下面是一些現場的代碼的摘錄(舊的SA版本,所以語法可能有點不同):
# Pull start and end dates from form
# ...
# Build a constraint if `start` and/or `end` have been set.
created = None
if start and end:
created = sa.sql.between(msg.c.create_time_stamp,
start.replace(hour=0, minute=0, second=0),
end.replace(hour=23, minute=59, second=59))
elif start:
created = (msg.c.create_time_stamp >=
start.replace(hour=0, minute=0, second=0))
elif end:
created = (msg.c.create_time_stamp <=
end.replace(hour=23, minute=59, second=59))
# More complex `from_` object built here, elided for example
# [...]
# Final query build
query = sa.select([unit.c.eli_uid], from_obj=[from_])
query = query.column(count(msg.c.id).label('sent'))
query = query.where(current_store)
if created:
query = query.where(created)
哪裏這個來自很多更復雜的代碼,但我想強調的日期範圍代碼在這裏。如果我必須使用字符串格式來構建SQL,那麼我可能會在某處引入SQL注入漏洞,因爲忘記引用值更容易。
在我開發了我的一個小項目之後,我決定嘗試僅使用MySQLDB,而不使用SQL Alchemy。
它工作正常,它是很容易使用,這裏是一個例子(我創建了一個小的類來處理所有的工作到數據庫)
import MySQLdb
from MySQLdb.cursors import DictCursor
class DatabaseBridge():
def __init__(self, *args, **kwargs):
kwargs['cursorclass'] = DictCursor
self.cnx = MySQLdb.connect (**kwargs)
self.cnx.autocommit(True)
self.cursor = self.cnx.cursor()
def query_all(self, query, *args):
self.cursor.execute(query, *args)
return self.cursor.fetchall()
def find_unique(self, query, *args):
rows = self.query_all(query, *args);
if len(rows) == 1:
return rows[0]
return None
def execute(self, query, params):
self.cursor.execute(query, params)
return self.cursor.rowcount
def get_last_id(self):
return self.cnx.insert_id()
def close(self):
self.cursor.close()
self.cnx.close()
database = DatabaseBridge(**{
'user': 'user',
'passwd': 'password',
'db': 'my_db'
})
rows = database.query_all("SELECT id, name, email FROM users WHERE is_active = %s AND project = %s", (1, "My First Project"))
(這是一個愚蠢的例子)。
它的工作原理就像一個魅力但,你必須考慮這些因素:不支持
multiprocessing
也行。但在另一方面,像SQLAlchemy的,有保護agains't SQL注入攻擊:
一個基本的查詢會是這樣的:
cursor.execute("SELECT * FROM users WHERE data = %s" % "Some value") # THIS IS DANGEROUS
但是,你應該做的:
cursor.execute("SELECT * FROM users WHERE data = %s", "Some value") # This is secure!
看到區別?再讀一遍;)
不同之處在於我用,
替換了%
:我們將參數作爲參數傳遞給execute,並且這些都被轉義了。當使用%
時,參數不會被轉義,從而導致SQL注入攻擊!
這裏的最後一句話是,它取決於您的使用情況以及您計劃如何處理您的項目。對我而言,SQLAlchemy過於誇張(這是一個基本的shell腳本!),所以MysqlDB非常完美。