Home > database >  db.create_all() not generating db
db.create_all() not generating db

Time:01-10

I'm trying to test Flask with SQLAlchemy and I stumbeld accross this problem. First, I have to note that I read all of the related threads and none of them solves my problem. I have a problem that db.create_all() doesn't generate the table I defined. I have model class in file person.py:

from website import db


class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, nullable=False)
    password = db.Column(db.String)
    width = db.Column(db.Integer)
    height = db.Column(db.Integer)
    agent = db.Column(db.String)
    user_data_dir = db.Column(db.String)

And in my website.py which is the file from where I launch the app:

from flask import Flask, jsonify, render_template, request
from flask_sqlalchemy import SQLAlchemy

# create the extension
db = SQLAlchemy()

def start_server(host, port, debug=False):
    from person import Person

    # create the app
    app = Flask(__name__,
                static_url_path='',
                static_folder='web/static',
                template_folder='web/templates')
    # configure the SQLite database, relative to the app instance folder
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///database0.db"
    # initialize the app with the extension
    db.init_app(app)

    print('initialized db')
    print('creating tables...')

    with app.app_context():
        db.create_all()

        db.session.add(Person(username="example33"))
        db.session.commit()

        person = db.session.execute(db.select(Person)).scalar()
        print('persons')
        print(person.username)


if __name__ == '__main__':
    start_server(host='0.0.0.0', port=5002, debug=True)

I think the problem might be that the Person class is not importing properly, because when I put the class inside the start_server function it executes fine and creates the table, but I don't know why this is happening. I followed all the advice and imported it before everything, and also I share the same db object between the 2 files

CodePudding user response:

I am reading the documentation, which explains that the function will

Create all tables stored in this metadata.

That leads me to believe Person is not associated with the db metadata.

You mentioned

when I put the class inside the start_server function it ... creates the table

Your from person import Person is nice enough, but I suspect we wanted a simple import person. In many apps the idiom would be import models.

Failing that, you may be able to point create_all in the right direction with this optional parameter:

tables – Optional list of Table objects, which is a subset of the total tables in the MetaData


Please let us know what technical approach worked for you.

CodePudding user response:

There is probably a better way to do this but this is the only way I could get this to work. You need to create a models.py file or w.e you wanna call it. Then all your database stuff goes in there. The db engine, ALL your models and a function to initialize it all. The reason is, you are having import issues where Person is imported but not fully and so the db doesn't have it in its metadata.

models.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()


class Person(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String, nullable=False)
    password = db.Column(db.String)
    width = db.Column(db.Integer)
    height = db.Column(db.Integer)
    agent = db.Column(db.String)
    user_data_dir = db.Column(db.String)

# All other models

def initialize_db(app: Flask):
    db.init_app(app)

    with app.app_context():
        db.create_all()

main.py

from flask import Flask
import models


def start_server(host, port, debug=False):
    app = Flask(__name__)
    # configure the SQLite database, relative to the app instance folder
    app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///database0.db"
    # initialize the app with the extension
    models.initialize_db(app)
    db = models.db
    
    with app.app_context():
        db.session.add(models.Person(username="example33"))
        db.session.commit()

        person = db.session.execute(db.select(models.Person)).scalar()
        print('persons')
        print(person.username)


if __name__ == '__main__':
    start_server(host='0.0.0.0', port=5002, debug=True)

  • Related