0

I'm building a backend for my iOS app and I choose to use Flask framework.

For the database part, I use flask-sqlalchemy to connect my mysql database.

When I put all my test code in a single file, everything works fine.

test.py

from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:pwd@localhost/test"
db = SQLAlchemy(app)


class player(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    def __init__(self, username, email):
        self.username = username
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.username

db.create_all()

However, when I split the code into different files in order to make the whole project structured, I got an error.

Here's my file structure:

.
├── config.py
├── app.py
├── app
    ├── __init__.py
    ├── api.py
    └── models.py
└── venv

config.py

SQLALCHEMY_DATABASE_URI = "mysql://root:pwd@localhost/test"

app.py

from app import app

if __name__ == '__main__':
    app.run(debug=True)

__init.py__

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

import config

app = Flask(__name__)
app.config.from_object("config")
db = SQLAlchemy(app)

import models
db.create_all()

models.py

from app import db

class player(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)

    def __init__(self, username, email):
        self.username = username
        self.email = email

    def __repr__(self):
        return '<User %r>' % self.username

When I ran __init__.py to create all the tables in models.py, I got error

sqlalchemy.exc.InvalidRequestError: Table 'player' is already defined for this MetaData instance. Specify 'extend_existing=True' to redefine options and columns on an existing Table object.

And when I check the database, I found that table player is created.

It seems that sqlalchemy is trying to create the tables repeatedly.

Why is that?

jinglei
  • 3,269
  • 11
  • 27
  • 46
  • 1
    Flask try create table on every run, such as you put db.create_all() into __init__.py You should put create db commands into separate script, try use Flask-Script and alembic (http://flask-script.readthedocs.io/en/latest/). Into test.py you can set db.drop_all() before db.create_all() – VelikiiNehochuha May 05 '16 at 13:55
  • I have left db.create_all() in my app init file without any problems. What I see different in your script from my scripts is that player model. I always define my models with propercase so try changing 'player(db.Model)' to 'Player(db.Model)' – 8oh8 Dec 16 '16 at 22:44
  • The error tells you that a `Table` instance has been included in the `MetaData` already. That means that *you* are trying to create the `Table` instances repeatedly, but have not included enough code here to demonstrate how and where. Are you using reflection? Please produce a [mcve]. – Ilja Everilä Feb 05 '18 at 07:38
  • 1
    How come you have `app.py` and `app/__init__.py`?! – Antti Haapala -- Слава Україні Feb 05 '18 at 08:10

1 Answers1

0

try

from app import models

instead of

import models

you are creating a circular import. See this link for more about circular imports

Community
  • 1
  • 1
betts
  • 1