如何在Flask-SQLAlchemy中以字符串形式传入数据库模型名称?
安全实现用字符串模型名执行Flask-SQLAlchemy查询的方法
这个问题我之前做项目时也碰到过,直接用字符串调用query肯定会报错,毕竟字符串本身只是文本,根本没有query属性嘛。下面给你两个安全可靠的实现思路,完全避开危险的eval操作:
方法一:利用Flask-SQLAlchemy内置的模型字典
Flask-SQLAlchemy的SQLAlchemy实例自带一个models字典,里面自动存储了所有你定义的模型类,键就是模型的类名(字符串形式)。你可以直接通过这个字典获取对应的模型类:
from flask import abort from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() # 假设你的User模型已经通过db.Model定义完成 row_id = 1 database_name = "User" # 获取目标模型类 target_model = db.models.get(database_name) # 先检查模型是否存在,避免后续报错 if not target_model: abort(404, description=f"Model {database_name} does not exist") # 正常执行查询 row = target_model.query.filter_by(id=row_id).first_or_404()
这种方法是官方推荐的,因为db.models只包含你已经注册的合法模型,不会引入未知代码,安全性拉满。
方法二:手动维护模型映射字典
如果想更可控(比如只允许特定模型被字符串调用),可以自己定义一个映射字典,把允许的模型类和对应的字符串名称关联起来:
from flask import abort from your_app.models import User, Post, Comment # 导入你项目中的模型 # 手动定义允许通过字符串调用的模型 ALLOWED_MODELS = { "User": User, "Post": Post, "Comment": Comment } row_id = 1 database_name = "User" target_model = ALLOWED_MODELS.get(database_name) if not target_model: abort(404, description=f"Model {database_name} is not accessible") row = target_model.query.filter_by(id=row_id).first_or_404()
这种方式的优势在于你可以严格控制哪些模型能被字符串调用,进一步降低风险,适合有严格权限控制的生产环境场景。
为什么绝对不能用eval?
很多人可能会想到用eval(database_name)直接把字符串转成类,但这种做法极度危险——如果database_name是用户输入的恶意字符串(比如"os.system('rm -rf /')"),会直接执行任意代码,造成毁灭性的安全漏洞。上面两种方法都完全避开了这种风险,是生产环境的首选。
内容的提问来源于stack exchange,提问作者cccnrc
相关产品推荐
相关产品推荐

