使用 Flask,我很想知道 SQLAlchemy 是否仍然是使用原始 SQL(直接SELECT x FROM table WHERE ...
)而不是使用 ORM 查询我的数据库的最佳方法,或者是否有更简单但功能强大的替代方法?
感谢您的回复。
使用 Flask,我很想知道 SQLAlchemy 是否仍然是使用原始 SQL(直接SELECT x FROM table WHERE ...
)而不是使用 ORM 查询我的数据库的最佳方法,或者是否有更简单但功能强大的替代方法?
感谢您的回复。
我一直使用 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
如果你不使用Python也没关系。但另一方面,就像 SQLAlchemy 一样,有针对 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!
看出区别了吗?再读一遍;)
不同之处在于我将%
, 替换为,
: 我们将参数作为 ... 参数传递给执行,这些都被转义了。使用时%
,参数不会被转义,从而启用 SQL 注入攻击!
最后一句话是,这取决于您的使用情况以及您计划对项目执行的操作。对我来说,SQLAlchemy 太过分了(它是一个基本的 shell 脚本!),所以 MysqlDB 是完美的。