首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
拉钩
V2EX  ›  Flask

flask 有关 create_all 之前是否需要导入模型类的问题?

  •  
  •   sevenQu · 154 天前 · 794 次点击
    这是一个创建于 154 天前的主题,其中的信息可能已经有所发展或是发生改变。
    • models 文件
    from flask.ext.sqlalchemy import SQLAlchemy
    db = SQLAlchemy()
    
    class Contact(db.Model):
        ...
    
    • app 里的__init__文件
    from flask import Flask
    from app.models import db
    
    def create_app():
        app = Flask(__name__)
    
        # 绑定数据库
        db.init_app(app)
    
    
        # 下面两种方法都可以创建数据库
        db.create_all(app=app)
    
        # with app.app_context():
        #     db.create_all()
    
        return app
    
    • 这样就已经可以创建数据库了,但我查的资料很多说 create_all()无法创建数据库,需要在启动文件里加上 from app.models import *,说需要将模型注册到 db 上,所以我不明白为什么如上的写法,没有引入 models 注册也可以成功创建数据库
    • 同时我想使用的的 flask-migrate,也需要将 model 引入到 migrate=Migrate(app=app,db=db)之前,不知道为什么要这样做?求解
    • 谢谢
    • 我可能描述的不完整,相似的问题点击跳转

    • 核心的问题就是创建数据库之前到底需不需要引入 models 模型,为什么?
    12 回复  |  直到 2018-07-17 19:53:47 +08:00
        1
    mink   154 天前
    不需要, 你在上面通过 from app.models import db 已经把模型和 db 绑定在一起了。create_app 中 db.init_app 是把 db 和当前的应用绑定在一起 只要使用 db.create_all 方法就可以调用 不需要引入模型
        2
    sevenQu   154 天前
    @mink 确实我试了,使用 db.create_all()确实可以创建数据库
        3
    sevenQu   154 天前
    @mink
    ```
    import os
    from app import create_app,db
    from flask_script import Manager,Shell
    from flask_migrate import Migrate,MigrateCommand

    # from app.models.wordRepertory import CET4,CET6,Kaoyan


    app=create_app(os.getenv('FLASK_CONFIG') or 'default')

    manager=Manager(app=app)
    migrate=Migrate(app=app,db=db)

    def make_shell_context():
    return dict(app=app,db=db)
    manager.add_command('shell',Shell(make_context=make_shell_context))
    manager.add_command('db',MigrateCommand)

    if __name__=='__main__':
    manager.run()
    ```


    在使用 migrate 的时候,应该怎么做?我试了,如果不在上面引入 models 里定义的类,就无法迁移自动生成数据表,希望可以帮忙解决一下
        4
    mink   154 天前
    @sevenQu 我不清楚 migrate 会不会自动生成数据表, 但是可以通过 db.create_all()完成初始化
    ````python
    @manager.command
    def init():
    db.create_all()

    $ python manage.py init

    ```
        5
    mink   154 天前
    @sevenQu flask-migrate 的 init 只是创建 migrations 的相关文件后续需要执行,migration 和 upgrade 才会记录版本和生成迁移脚本执行数据库初始化 https://juejin.im/post/5b1935355188257d492ae266
        6
    sevenQu   154 天前
    @mink 会自己生成数据表的,可以完全不使用 create_all 创建。我自己试的结果是,前面需要引入 models 里的类,如果将 model 拆分,导入会很多,感觉不优雅也感觉没必要
        7
    sevenQu   154 天前
    @mink 谢谢,看来是不可避免的要引入了,十分感谢
        8
    lniwn   154 天前
    在 create_all 之前,要引入 models 文件,否则 Model 的 metadata 中没有你定义的类,你定义的表类最终会存储到 db.Model.metadata.tables 中,使用方式可以参考<https://github.com/lniwn/my_proxypool/blob/0a09c231d2f8ca7383899d8aa34153965948bd93/datacenter/datacenter.py#L38>。
    这样不可避免的会导致循环引用的问题,一个比较好的解决方法是使用 import_string 来动态导入,这个方法在 werkzeug 中,我自己也参考着实现了一个<https://github.com/lniwn/my_proxypool/blob/0a09c231d2f8ca7383899d8aa34153965948bd93/datautil/generalutils.py#L8>
        9
    sevenQu   154 天前
    @lniwn 这段获取 db.Model.metadata.tables 里的表类的代码在 create_all()方法的源码里有,所以确实不需要引入 models 里的类
        10
    sevenQu   153 天前
    @lniwn 好像我错了,是需要导入 models 的,导入的话,还有几个问题,希望您可以帮忙看看,我把代码放到了 github,问题在 readme.md ,十分希望您可以帮忙解释一下,谢谢,https://github.com/seven-share/flaskMigrateTry
        11
    sevenQu   153 天前
    @mink 老铁,我又试了一下,发现不引入 models 是不能创建数据表的,希望您能看看我的源代码,看看是不是确实需要引入,同时我还有几个新问题写在了 github 的 readme 里,方便的话,希望您可以帮忙解决一下,十分感谢,https://github.com/seven-share/flaskMigrateTry
        12
    greyli   148 天前
    在知乎写了一个同一问题的回答,供需要的人参考:
    https://www.zhihu.com/question/284904297/answer/444926077
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2446 人在线   最高记录 4019   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 17ms · UTC 12:57 · PVG 20:57 · LAX 04:57 · JFK 07:57
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1