Python-Flask-SQLAlchemy模型之创建table时,如何声明基类(这个类不会创建表,可以被继承)

class Base(db.Model, ClassIterator):
    # Flask-SQLAlchemy创建table时,如何声明基类(这个类不会创建表,可以被继承)
    # 方法就是把__abstract__这个属性设置为True,这个类为基类,不会被创建为表!
    # 只要设置了__abstract__ = True,这个基类无法实现relationship和ForeignKey等关联方法【只能由子类继承去关联】

    __abstract__ = True

务必注意:如果你多个表要继承base,而这些表要分别创建就必须把基类Base禁用创建表,而仅能被继承【否则,base创建了,其他子类表无法创建】 

 

其次最重要的就是 :只要设置了__abstract__ = True,这个基类无法实现relationship和ForeignKey等关联方法【只能由子类继承去关联】

<think>我们使用Flask-SQLAlchemy,可以通过已有的数据库结构反向生成模型(Model Classes)。这通常称为“反射”(reflection)或“自动生成模型”。 但注意:Flask-SQLAlchemy本身没有直接提供从数据库生成模型的命令,但我们可以使用SQLAlchemy的自动映射功能,或者使用第三方工具如`sqlacodegen`。 这里提供两种方法: 方法一:使用SQLAlchemy的自动映射(Automap) 这种方法适用于已有数据库,我们通过反射结构来创建模型。 方法二:使用sqlacodegen工具(推荐) `sqlacodegen`是一个第三方库,它可以从现有数据库生成SQLAlchemy模型代码。 下面分别介绍这两种方法。 方法一:使用SQLAlchemy的自动映射(在Flask中集成) 步骤: 1. 创建一个Flask应用和SQLAlchemy实例。 2. 使用SQLAlchemy的自动映射功能。 示例代码: 注意:这种方法生成的模型是直接继承自`db.Model`(Flask-SQLAlchemy基类),而是继承SQLAlchemy基类。因此,在Flask中可能需要调整。 方法二:使用sqlacodegen 安装sqlacodegen: ```bash pip install sqlacodegen ``` 然后,使用命令行生成模型代码。例如: ```bash sqlacodegen --outfile models.py mysql+pymysql://username:password@localhost/dbname ``` 但是,在Flask项目中,我们通常希望模型继承自`db.Model`(即Flask-SQLAlchemy基类)。为此,我们可以使用`--flask`选项: ```bash sqlacodegen --flask --outfile models.py mysql+pymysql://username:password@localhost/dbname ``` 这样生成的模型就会使用`db.Model`作为基类。 然而,有我们可能需要在代码中动态生成模型(而是生成静态文件),或者需要集成到Flask应用中。这,我们可以使用方法一,或者使用`sqlacodegen`的库形式(但sqlacodegen主要设计为命令行工具)。 下面提供一个在Flask应用中使用自动映射(方法一)的示例代码: 注意:自动映射不会生成关系(如外键关系),它只会生成基本的列。如果需要关系,可能需要手动添加。 示例(自动映射): ```python from flask import Flask from flask_sqlalchemy import SQLAlchemy from sqlalchemy.ext.automap import automap_base app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'your_database_uri' db = SQLAlchemy(app) # 使用automap Base = automap_base() # 反射数据库 Base.prepare(db.engine, reflect=True) # 获取映射后的 User = Base.classes.user # 假设数据库中有一个名为'user'的 # 现在你可以使用User来查询 @app.route('/') def index(): users = db.session.query(User).all() # ... 处理 return "Hello" if __name__ == '__main__': app.run() ``` 但是,上述方法中,我们得到的User继承自`db.Model`,而是继承自`Base`(它是`declarative_base`的一个实例)。在Flask-SQLAlchemy中,我们通常希望使用`db.Model`。因此,另一种做法是使用`db.Model`作为基类,然后反射结构到该基类上。 实际上,Flask-SQLAlchemy的`db`对象有一个`Model`,我们可以通过以下方式反射: ```python class User(db.Model): __tablename__ = 'user' __table_args__ = {'autoload': True, 'autoload_with': db.engine} # 这样,User就通过反射加载了结构 ``` 我们可以为每个写一个这样的。但是,如果很多,我们可以动态创建这些。例如: ```python from sqlalchemy import MetaData metadata = MetaData() metadata.reflect(bind=db.engine) tables = metadata.tables for table_name in tables: # 动态创建 cls = type(table_name, (db.Model,), { '__table__': tables[table_name], '__mapper_args__': { 'primary_key': list(tables[table_name].primary_key.columns) } }) # 将添加到全局变量中,以便使用 globals()[table_name] = cls ``` 但是,动态创建可能利于IDE的智能提示,而且关系(外键)可能不会自动处理。 因此,对于生产环境,推荐使用`sqlacodegen`生成模型文件,然后手动调整关系部分。 总结: 1. 如果只是需要快速反射结构进行查询,可以使用自动映射(automap)或者使用`__table_args__`设置`autoload`。 2. 如果需要完整的模型(包括在Flask中直接使用),推荐使用`sqlacodegen`生成模型文件,然后手动调整。 下面给出一个使用`autoload`的示例(针对单个): ```python class User(db.Model): __tablename__ = 'user' __table_args__ = {'autoload': True, 'autoload_with': db.engine} ``` 这样,User就会反射数据库中的'user'的所有列。 注意:这种方法不会反射关系(比如外键关联的其他的关系属性),需要自己手动添加。 因此,对于复杂的数据库结构,建议使用`sqlacodegen`生成基础模型,然后手动添加关系。 最后,提供一个使用`sqlacodegen`生成Flask-SQLAlchemy模型的命令行示例: ```bash sqlacodegen --flask --outfile models.py mysql+pymysql://user:password@localhost/mydatabase ``` 然后,在Flask应用中导入这个models.py即可。 如果数据库连接信息在Flask配置中,也可以先设置环境变量,然后使用相同的连接字符串。 由于`sqlacodegen`是一个独立的工具,这里展示其生成的代码,但你可以查看生成的models.py文件。 希望这些方法能帮助你反向生成模型。 §§相关问题§§: 1. 如何在使用`autoload`反射结构,只反射特定的列? 2. 使用`sqlacodegen`生成模型,如何排除某些? 3. 在Flask-SQLAlchemy中,如何动态创建模型(即运行根据名动态生成模型)? 4. 反射生成的模型,如何添加自定义方法?</think>### 反向生成 SQLAlchemy 模型的方法 根据数据库结构反向生成 SQLAlchemy 模型主要有两种方法:使用 `sqlacodegen` 工具或 SQLAlchemy 的反射功能。以下是详细解决方案: --- ### 方法一:使用 sqlacodegen 工具(推荐) **安装:** ```bash pip install sqlacodegen ``` **使用命令:** ```bash # 基础命令 sqlacodegen postgresql://user:password@localhost/dbname --outfile models.py # 生成 Flask-SQLAlchemy 模型(添加 --flask 参数) sqlacodegen mysql+pymysql://user:password@localhost/dbname --flask --outfile models.py # 排除特定(如排除临 temp_*) sqlacodegen sqlite:///database.db --flask --tables users,products --outfile models.py ``` **生成示例(models.py):** ```python from flask_sqlalchemy import SQLAlchemy db = SQLAlchemy() class User(db.Model): __tablename__ = 'users' id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(80), nullable=False) email = db.Column(db.String(120), unique=True) created_at = db.Column(db.DateTime, server_default=db.func.now()) orders = db.relationship('Order', backref='user', lazy=True) class Order(db.Model): __tablename__ = 'orders' id = db.Column(db.Integer, primary_key=True) user_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False) amount = db.Column(db.Float) ``` --- ### 方法二:使用 SQLAlchemy 反射(动态生成) 在代码中动态反射结构: ```python from flask import Flask from flask_sqlalchemy import SQLAlchemy from sqlalchemy import inspect app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db' db = SQLAlchemy(app) # 动态反射模型 def reflect_models(): inspector = inspect(db.engine) for table_name in inspector.get_table_names(): # 创建动态模型 cls = type( table_name.capitalize(), # 名(如 Users) (db.Model,), { '__tablename__': table_name, '__table_args__': {'autoload': True, 'autoload_with': db.engine} } ) globals()[cls.__name__] = cls # 添加到全局命名空间 reflect_models() # 使用示例 if __name__ == '__main__': users = globals()['Users'].query.all() # 访问 Users 模型 print([u.name for u in users]) ``` **关键点说明:** 1. `inspect(db.engine)`:获取数据库元数据 2. `autoload=True`:自动加载结构 3. 动态创建:使用 `type()` 动态生成继承自 `db.Model` 的 4. 外键关系需手动添加(反射不会自动生成 relationships) --- ### 手动添加关系的示例 如果有外键关联,需手动补充 `db.relationship`: ```python class Order(db.Model): __tablename__ = 'orders' __table_args__ = {'autoload': True} # 手动添加关系(假设存在 user_id 外键) user = db.relationship('User', backref=db.backref('orders', lazy=True)) ``` --- ### 两种方法对比 | **特性** | **sqlacodegen** | **反射 (autoload)** | |------------------------|-------------------------------------|----------------------------------| | 输出结果 | 生成静态 Python 文件 | 运行动态生成模型 | | 关系 (relationships) | 自动生成外键关系 | 需手动添加 | | 自定义修改 | 可直接编辑生成的代码 | 需在动态生成后修改 | | 适用场景 | 项目初始化/模型固化 | 动态数据库结构/临查询 | --- ### 注意事项 1. **复杂关系**:多对多、复合主键等复杂结构可能需要手动调整 2. **列覆盖**:可覆盖自动生成的列定义(如添加自定义验证): ```python class User(db.Model): __tablename__ = 'users' __table_args__ = {'autoload': True} # 覆盖 email 列定义 email = db.Column(db.String(120), nullable=False, unique=True) ``` 3. **视图支持**:使用 `--views` 参数可反射数据库视图(sqlacodegen)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值