重构后遇TypeError:'Connection'对象不可下标访问的问题排查
TypeError: 'Connection' object is not subscriptable 错误排查与解决
错误信息
File "/Applications/MAMP/htdocs/evahub/backend/rest_delete.py", line 23, in deleteDocument user = getDbUser(username) File "/Applications/MAMP/htdocs/evahub/backend/db_users_broker.py", line 25, in getDbUser usersCollection = db["users"] TypeError: 'Connection' object is not subscriptable
相关代码
rest_delete.py 片段
... user = getDbUser(username) ...
db_users_broker.py
from db_config import getDb db = getDb() def getDbUser(username): usersCollection = db["users"] uq = {"username": username} user = usersCollection.find_one(uq) if user == None: return None else: return user
db_config.py
from flaskext.mysql import MySQL from flask import Flask app = Flask(__name__) app.config["MYSQL_DATABASE_USER"] = "root" app.config["MYSQL_DATABASE_PASSWORD"] = "root" app.config["MYSQL_DATABASE_DB"] = "evahub" app.config["MYSQL_DATABASE_HOST"] = "localhost" def getDb(): mysql = MySQL( app, prefix="", host=app.config["MYSQL_DATABASE_HOST"], user=app.config["MYSQL_DATABASE_USER"], password=app.config["MYSQL_DATABASE_PASSWORD"], db=app.config["MYSQL_DATABASE_DB"], autocommit=True, ) connection = mysql.connect() return connection
错误原因
- API逻辑混淆:你当前使用
flaskext.mysql操作MySQL数据库,但代码完全沿用了MongoDB的操作风格:db["users"]是MongoDB中获取集合的写法,而MySQL的Connection对象不支持下标操作,因此触发TypeError。usersCollection.find_one(uq)是MongoDB的查询方法,MySQL没有对应API,必须用SQL语句实现查询。
- 连接初始化冗余:
getDb()每次调用都会重新创建MySQL实例,且全局赋值db = getDb()会导致连接长期占用,容易引发超时或资源泄漏问题。
解决方案
1. 优化数据库连接初始化(db_config.py)
全局仅初始化一次MySQL实例,避免重复创建资源:
from flaskext.mysql import MySQL from flask import Flask app = Flask(__name__) app.config["MYSQL_DATABASE_USER"] = "root" app.config["MYSQL_DATABASE_PASSWORD"] = "root" app.config["MYSQL_DATABASE_DB"] = "evahub" app.config["MYSQL_DATABASE_HOST"] = "localhost" # 全局初始化一次MySQL实例 mysql = MySQL(app) def getDb(): return mysql.connect()
2. 重写用户查询逻辑(db_users_broker.py)
改用MySQL的SQL查询语法,替换MongoDB风格代码:
from db_config import getDb def getDbUser(username): # 每次查询时临时获取连接,用完立即关闭 connection = getDb() # 开启字典游标,让返回结果与MongoDB文档格式一致(键值对) cursor = connection.cursor(dictionary=True) # 参数化SQL查询,避免SQL注入 query = "SELECT * FROM users WHERE username = %s" cursor.execute(query, (username,)) # 获取单条结果,对应MongoDB的find_one方法 user = cursor.fetchone() # 释放资源 cursor.close() connection.close() return user
关键说明
- MySQL中没有“集合”概念,对应的是数据表,必须通过SQL语句操作数据。
- 不要全局保存数据库连接,应遵循“即用即取、用完即关”的原则,避免连接超时或资源浪费。
- 使用参数化查询(
%s占位符)是MySQL操作的安全规范,能有效防止SQL注入风险。
内容的提问来源于stack exchange,提问作者The Outstanding Question Asker
相关产品推荐
相关产品推荐

