Search code examples
pythonflaskpeewee

Flask + Peewee: where to create tables?


Instead of flask-peewee I'm using plain peewee package.

Here's the way I'm initializing the database:

import os

# just extending the BaseFlask with yaml config reader
from . extensions.flask_app import Flask

# peewee's wrapper around the database
from playhouse.flask_utils import FlaskDB


db_wrapper = FlaskDB() 


# define the application factory
def create_app(env):

    app = Flask(__name__)

    # load config depending on the environment
    app.config.from_yaml(os.path.join(app.root_path, 'config.yml'), env)

    # init extensions
    db_wrapper.init_app(app)

    # ...

I know that I should call this to create tables:

from . models import User

db_wrapper.database.connect()
db_wrapper.database.create_tables([User])

But where do I put the table creation code, so that the database would be already initialized?

Edit

Looking at the docs I found out that I can use User.create_table(fail_silently=True) like that:

# in app/__init__.py

# define the application factory
def create_app(env):

    app = Flask(__name__)

    # load config depending on the environment
    app.config.from_yaml(os.path.join(app.root_path, 'config.yml'), env)

    # init extensions
    db_wrapper.init_app(app)

    create_tables();

    # rest of the initialization

def create_tables():

    from . models import User    
    User.create_table(fail_silently=True)

Is it alright to do it here? Or is there a better way/tool for this?

Edit

Figured it out. Please, see my answer below.


Solution

  • Update

    I didn't know about the built-in CLI support in Flask. I don't know whether you should consider such an approach at all, since you can do things out of the box (see documntation).


    I can utilize the flask-script package. I've done it before, just overlooked it.

    Activate your virtual environment and run:

    pip install flask-script

    Then create manage.py file in your root directory, add these lines:

    import os
    from app import create_app, db_wrapper
    from app.models import *
    from flask_script import Manager, Shell
    
    # create the application instance    
    app = create_app(os.getenv('FLASK_ENV', 'development'))
    
    # instantiate script manager
    manager = Manager(app)
    
    def make_shell_context():
        return dict(app=app, db_wrapper=db_wrapper, User=User)
    
    
    @manager.command
    def run_shell():
        Shell(make_context = make_shell_context).run(no_ipython=True, no_bpython=True)
    
    
    # here's my simple command
    @manager.command
    def create_tables():
        User.create_table(fail_silently=True)
    
    
    @manager.command
    def run_tests():
        import unittest
        tests = unittest.TestLoader().discover('tests')
        unittest.TextTestRunner(verbosity=2).run(tests)
    
    
    # run it
    if __name__ == '__main__':
        manager.run()