"这需求改不了!" 听到后端同事第N次拒绝修改订单查询功能时,作为产品经理的小李感到无比沮丧,他们公司电商平台的后台数据库是微软的SQL Server(MSSQL),而现有的Java系统过于笨重,每次业务调整都要等上两三周,直到某天,团队里新来的Python工程师小王提议:"要不我们用Flask重构这部分?对接MSSQL其实很简单。"
一周后,当小李看到新的订单查询接口响应时间从原来的2秒降到200毫秒时,她终于明白为什么现在这么多企业选择Python+Flask来构建轻量级Web服务了。
在开始之前,我们需要准备好开发环境,假设你已经安装了Python 3.8+(截至2025年8月,Python 3.10是主流稳定版本),下面是其他必要的准备工作:
# 创建虚拟环境(推荐) python -m venv flask_mssql_env source flask_mssql_env/bin/activate # Linux/Mac flask_mssql_env\Scripts\activate # Windows # 安装核心依赖 pip install flask pyodbc flask-sqlalchemy
对于MSSQL连接,Windows系统通常已经自带ODBC驱动,而Linux/Mac需要额外安装:
# Ubuntu/Debian sudo apt-get install unixodbc unixodbc-dev freetds-dev tdsodbc # CentOS/RHEL sudo yum install unixODBC unixODBC-devel freetds freetds-devel
Flask连接MSSQL主要有两种方式:直接使用pyodbc,或者通过SQLAlchemy ORM,我们先看基础配置:
# config.py class Config: MSSQL_SERVER = 'your_server.database.windows.net' # 或本地服务器地址 MSSQL_DATABASE = 'your_database' MSSQL_USERNAME = 'your_username' MSSQL_PASSWORD = 'your_password' SQLALCHEMY_DATABASE_URI = f"mssql+pyodbc://{MSSQL_USERNAME}:{MSSQL_PASSWORD}@{MSSQL_SERVER}/{MSSQL_DATABASE}?driver=ODBC+Driver+17+for+SQL+Server" SQLALCHEMY_TRACK_MODIFICATIONS = False
注意这里的ODBC Driver 17 for SQL Server
是驱动名称,根据你的实际环境可能需要调整。
让我们创建一个完整的商品管理模块示例:
# app.py from flask import Flask, jsonify, request from flask_sqlalchemy import SQLAlchemy from config import Config app = Flask(__name__) app.config.from_object(Config) db = SQLAlchemy(app) # 定义商品模型 class Product(db.Model): __tablename__ = 'products' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(100), nullable=False) price = db.Column(db.Float, nullable=False) stock = db.Column(db.Integer, default=0) def to_dict(self): return { 'id': self.id, 'name': self.name, 'price': self.price, 'stock': self.stock } @app.route('/products', methods=['GET']) def get_products(): products = Product.query.all() return jsonify([product.to_dict() for product in products]) @app.route('/products', methods=['POST']) def add_product(): data = request.get_json() new_product = Product( name=data['name'], price=data['price'], stock=data.get('stock', 0) ) db.session.add(new_product) db.session.commit() return jsonify(new_product.to_dict()), 201 if __name__ == '__main__': app.run(debug=True)
直接使用ORM虽然方便,但在处理复杂查询或大数据量时可能会遇到性能瓶颈,以下是几个实战优化技巧:
对于复杂查询,可以直接执行原生SQL:
@app.route('/products/expensive', methods=['GET']) def get_expensive_products(): sql = "SELECT * FROM products WHERE price > 100 ORDER BY price DESC" result = db.session.execute(sql) products = [dict(row) for row in result] return jsonify(products)
from sqlalchemy import func @app.route('/products/paged', methods=['GET']) def get_paged_products(): page = request.args.get('page', 1, type=int) per_page = request.args.get('per_page', 10, type=int) pagination = Product.query.paginate(page=page, per_page=per_page) return jsonify({ 'items': [product.to_dict() for product in pagination.items], 'total': pagination.total, 'pages': pagination.pages, 'current_page': pagination.page })
在config.py中添加:
SQLALCHEMY_ENGINE_OPTIONS = { 'pool_size': 10, 'max_overflow': 20, 'pool_timeout': 30, 'pool_recycle': 3600 }
@app.route('/products/discount', methods=['POST']) def apply_discount(): discount_rate = request.json.get('rate', 0.1) try: # 调用名为sp_apply_discount的存储过程 db.session.execute( "EXEC sp_apply_discount :rate", {'rate': discount_rate} ) db.session.commit() return jsonify({'status': 'success'}) except Exception as e: db.session.rollback() return jsonify({'error': str(e)}), 500
@app.route('/orders', methods=['POST']) def create_order(): try: data = request.json # 开始事务 db.session.begin() # 扣减库存 for item in data['items']: product = Product.query.get(item['product_id']) if product.stock < item['quantity']: raise ValueError(f"产品 {product.name} 库存不足") product.stock -= item['quantity'] db.session.add(product) # 创建订单记录 new_order = Order( user_id=data['user_id'], total=data['total'] ) db.session.add(new_order) db.session.commit() return jsonify({'order_id': new_order.id}), 201 except Exception as e: db.session.rollback() return jsonify({'error': str(e)}), 400
如果在云服务器上连接MSSQL出现超时,检查以下几点:
SQLALCHEMY_DATABASE_URI += "&connect_timeout=30&login_timeout=30"
确保数据库和连接使用相同的编码,可以在连接字符串中添加:
SQLALCHEMY_DATABASE_URI += "&charset=utf8"
MSSQL默认使用服务器时区,可能导致时间字段显示不一致:
from datetime import datetime, timezone # 写入时转换为UTC now = datetime.now(timezone.utc) # 或者从配置层面解决 app.config['SQLALCHEMY_ENGINE_OPTIONS'] = { 'connect_args': { 'timezone': 'utc' } }
永远不要硬编码凭据:使用环境变量或配置管理工具
import os app.config['MSSQL_PASSWORD'] = os.getenv('DB_PASSWORD')
使用参数化查询防止SQL注入
# 错误做法 db.session.execute(f"SELECT * FROM users WHERE name = '{name}'") # 正确做法 db.session.execute("SELECT * FROM users WHERE name = :name", {'name': name})
最小权限原则:数据库用户只授予必要权限
通过本文的实践,我们可以看到Flask与MSSQL的集成既保持了Python的简洁高效,又能充分利用MSSQL作为企业级数据库的强大功能,特别是在需要快速迭代的业务场景中,这种组合能够显著提升开发效率。
随着Python生态的持续发展(截至2025年8月,PyODBC已经支持MSSQL 2022的所有新特性),以及Flask框架的轻量级优势,这种技术栈正在被越来越多的企业采用,既适用于初创公司的快速原型开发,也能满足中大型企业的性能需求。
下次当你面对老旧系统改造需求时,不妨考虑用Flask+MSSQL这个"轻量级拳击手"来替代那些"笨重的相扑选手",或许会收获意想不到的效果。
本文由 兆韵宁 于2025-08-03发表在【云服务器提供商】,文中图片由(兆韵宁)上传,本平台仅提供信息存储服务;作者观点、意见不代表本站立场,如有侵权,请联系我们删除;若有图片侵权,请您准备原始证明材料和公证书后联系我方删除!
本文链接:https://vps.7tqx.com/wenda/522946.html
发表评论