Basically I'm trying to make a Flask app using flask-sqlalchemy. I want to first load up a bunch of data into my database (database.py). However, I can't get this to work or even create the myapp.db file.
I'm getting no errors, however myapp.db file is not being created.
>>> db.engine
Engine(sqlite://)
The above should be myapp something, I'm pretty sure.
I have simplified my code to make it more concise to the problem.
Here I have my app:
from flask import Flask
import os
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
db_path = os.path.join(os.path.dirname(__file__), 'myapp.db')
db_uri = 'sqlite:///{}'.format(db_path)
SQLALCHEMY_DATABASE_URI = db_uri
db = SQLAlchemy(app)
from views import *
if __name__ == '__main__':
app.secret_key = os.urandom(12)
app.run(debug=True)
And I want to run my database.py to load all my data - which in my mind should be creating a myapp.db file??:
from flask_sqlalchemy import SQLAlchemy
import os
import re
from myapp import app
from models import *
## Creates our database
db.create_all()
username = test
password = test
user = User(username=username, password=password)
db.session.add(user)
db.session.commit()
Here is my models.py
from flask_sqlalchemy import SQLAlchemy
from myapp import app
# create a new SQLAlchemy object
db = SQLAlchemy(app)
class User(db.Model):
""""""
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String, nullable=False)
password = db.Column(db.String, nullable=False)
Changing
SQLALCHEMY_DATABASE_URI = db_uri
to
app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
fixed it.
Related
I have some difficulties with the library lask-sqlalchemy, I tried to create my database with the code bellow, i have no error but no table created.
_init.py
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
app.config.from_json("C:/Users/lquastana/PycharmProjects/flask_demo/conf/api-config.json")
app.app_context().push()
db.py
from flask_sqlalchemy import SQLAlchemy
from api_lab import app
db = SQLAlchemy(app)
member.py
from api_lab.models.db import db
class Member(db.Model):
__table_args__ = {"schema": "public"}
id = db.Column(db.BigInteger,
primary_key=True,
autoincrement=True)
id_company = db.Column(db.BigInteger,
db.ForeignKey("compagny.id"),
index=True,
nullable=False)
nom = db.Column(db.String(80), unique=True, nullable=False)
age = db.Column(db.Integer, unique=True, nullable=False)
def __repr__(self):
return '<Member %r>' % self.nom
run_api.py
from api_lab import app
from api_lab.models.db import db
def main():
host = app.config["ENV"]["HOST"]
port = app.config["ENV"]["PORT"]
debug = app.config["ENV"]["DEBUG"]
app.run(host=host, port=port, debug= debug)
if __name__ == '__main__':
db.create_all()
#main()
You should put all initialization related logic into init.py
Use SQLAlchemy to setup a db connection with your app.config
init.py
from api_lab import app
from api_lab.models.db import db
from flask_sqlalchemy import SQLAlchemy
app.config.from_json("C:/Users/lquastana/PycharmProjects/flask_demo/conf/api-config.json")
app.app_context().push()
db = SQLAlchemy(app)
# initialize the DB
db.create_all()
I'm having trouble creating a modular application using Flask using blueprints. I'm not sure how to migrate models defined in blueprints.
My app looks as follows:
- app
- __init__.py
- user
__init__.py
models.py
app.__init__.py looks as follows:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import Config
from flask_migrate import Migrate
from app.auth import bp as user_bp
db = SQLAlchemy()
app = Flask(__name__)
app.config.from_object(Config)
app.register_blueprint(user_bp, url_prefix='/user')
migrate = Migrate(app, db)
from app.auth.models import User
user/.__init__.py:
from flask import Blueprint
bp = Blueprint('user', __name__)
user/models.py:
from app import db
class User(db.Model):
user_id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(128))
last_name = db.Column(db.String(128))
user_name = db.Column(db.String(120))
password_hash = db.Column(db.String(220))
def __repr__(self):
return '<User {}>'.format(self.email)
When trying to run flask db migrate... no models are being detected and I think I have some sort of circular dependency.
Can someone please explain how to do this properly?
The User model (user/models.py) should be imported somewhere in the application, try to import into the blueprint file (user/__init__.py)
from flask import Blueprint
from app.user.models import User
bp = Blueprint('user', __name__)
app.py
from flask import Flask
from flask_restful import Resource, Api
from user import user_blueprint
from flask_cors import CORS
app = Flask(__name__)
api = Api(app)
app.register_blueprint(user_blueprint)
cors = CORS(app, resources={r"/*": {"origins": "*"}})
if __name__ == '__main__':
app.run(debug=True)
model/user.py
from sqlalchemy import Column, INTEGER, String
class User(Base):
__tablename__ = 'USER'
__table_args__ = {'schema': 'MAPPING'}
ID = Column(INTEGER(11), primary_key=True)
FIRST_NAME = Column(String(255), nullable=False, server_default=text("''"))
LAST_NAME = Column(String(255), nullable=False, server_default=text("''"))
EMAIL = Column(String(255), nullable=False, server_default=text("''"))
route/user_route
from flask import Blueprint, jsonify, request
from flask_restful import Resource, Api
user_blueprint = Blueprint('app/', __name__)
user_api = Api(user_blueprint, prefix='/')
class User(Resource):
def get(self):
db_conn = //db connection Object
results = // your query
db_conn.close()
return jsonify(results)
user_api.add_resource(User, '/user')
I'm new to Flask, and having some issues setting up a very basic Flask app.
Right now, I'm trying to get the user to submit a form on the homepage and then save that form to a SQL database.
However, when the user submits the form, I get the following error
sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: contact [SQL: 'INSERT INTO contact (name, email) VALUES (?, ?)'] [parameters: ('aaa', 'aaa')] (Background on this error at: http://sqlalche.me/e/e3q8)
Relevant code is below:
app/models.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, BooleanField, SubmitField
from wtforms.validators import DataRequired
class ContactForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
email = PasswordField('Email', validators=[DataRequired()])
submit = SubmitField('submit')
app/__init__.py
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
from app import routes, models
app/config.py
import os
basedir = os.path.abspath(os.path.dirname(__file__))
class Config(object):
SECRET_KEY = os.environ.get('SECRET_KEY') or 'some-secret-key'
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 'sqlite:///' + os.path.join(basedir, 'app.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
enter code here
Where could I be going wrong here? Do I have to call db.create_all() somewhere? If so, where?
Thanks!
Edit: I've also run
flask db init
flask db migrate
flask db upgrade
Create a model in models.py:
from __init__.py import db
class ContactModel(db.Model):
__tablename__ = 'contact'
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(120))
email = db.Column(db.String(120))
def save_to_db(self):
db.session.add(self)
db.session.commit()
Then in init.py:
from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
#create all db tables
#app.before_first_request
def create_tables():
from models import ContactModel
db.create_all()
from app import routes, models
If you are using flask-migrate library, you should run commands below to create and apply migrations. Database and tables will be created.
flask db migrate
flask db upgrade
Before running this commands you should create models. Models objects represent tables on a database. In your case, it may look like this
class Contact(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
email = db.Column(db.String(120), unique=True, nullable=False)
I had the same issue. In my case I was querying the database in a forms.py and this was imported to routes.py.
So the problem was basically that the database was queried in the code before it could be created, as classes are loaded before the server starts and an eventual init happens.
The accepted answer didn't work for me.
Unfortunately, I haven't found a clean solution for this. So I ended up with a workaround for this.
In my case I wanted to show files in a dropdown list, so I initialized them empty the first time:
try:
profile_files = [ (file.path, file.filename[:-4])
for file in File.query.filter_by(type=2).order_by(File.created.desc()).all()]
except sqlalchemy.exc.OperationalError as e:
profile_files = []
So the general workaround would be:
try:
# Your DB query
except sqlalchemy.exc.OperationalError as e:
# create placeholder until your DB is ready
Now I can use all the terminal commands again:
flask db init
flask db migrate
flask db upgrade
Hope this is helpful to someone!
I am following this tutorial: getting started with flask-login.
However I am stuck at step 5 where I start to use SQLAlchemy. I believe the problem might be circular importing, based on what I have read but I'm still a little new to Python coding. This web app is a little project I am doing in my free time.
So I guess my overall question is, is this circular importing, and if not does anyone see what I might be doing wrong here? I am also running this using virtualenv using Python 2.7.
File Structure:
-noteapp
-noteapp
-db
-forms
-static
-templates
-views
__init__.py
app.py
models.py
This is my app.py file
from flask import Flask
from flask_login import LoginManager
from noteapp.models import db
from noteapp.views.index import bp as index_bp
from noteapp.views.createnote import bp as createnote_bp
from noteapp.views.signup import bp as signup_bp
def init_db():
db.init_app(app)
db.app = app
db.create_all()
app = Flask(__name__)
app.secret_key = 'removed for reasons'
app.config['SQLALCHEMY_DATABASE_URI'] = 'removed for reasons'
db = SQLAlchemy(app)
login_manager = LoginManager(app)
login_manager.init_app(app)
app.register_blueprint(index_bp)
app.register_blueprint(createnote_bp)
app.register_blueprint(signup_bp)
if __name__ == '__main__':
app.init_db()
app.run(debug=True)
This is my models.py file:
from noteapp.app import app
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy(app)
class User(db.Model):
email = db.Column(db.String(80), primary_key=True, unique=True)
password = db.Column(db.String(80))
def __init__(self, email, password):
self.email = email
self.password = password
def __repr__(self):
return '<User %r>' % self.email
You are correct you have a circle import issue.
At app.py you import from noteapp.models import db,
and at models.py you import from noteapp.app import app
A quick fix could be:
at models.py use db = SQLAlchemy() without the app.
At the app.py module, import db from models.py and do db.init_app(app)
also remove db = SQLAlchemy(app) from your app.py
your app.py should look like this..
from noteapp.models import db
...
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'removed for reasons'
...
def init_db():
db.init_app(app)
db.app = app
db.create_all()
...
if __name__ == '__main__':
app.init_db()
app.run(debug=True)
models.py should look like this:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model):
email = db.Column(db.String(80), primary_key=True, unique=True)
password = db.Column(db.String(80))
def __init__(self, email, password):
self.email = email
self.password = password
def __repr__(self):
return '<User %r>' % self.email
This question already has an answer here:
Tyring to set up modelview with Flask-Admin causes ImportError
(1 answer)
Closed 5 years ago.
I have a flask app which I am trying to run. It seems when I run python app.py, there is a circular import of some sort. Here is the code for both my models.py and app.py:
models.py
import datetime
from app import bcrypt, db
class User(BaseModel, db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
email = db.Column(db.String(255), unique=True, nullable=False)
password = db.Column(db.String(255), nullable=False)
registered_on = db.Column(db.DateTime, nullable=False)
admin = db.Column(db.Boolean, nullable=False, default=False)
def __init__(self, email, password, admin=False):
self.email = email
self.password = bcrypt.generate_password_hash(password)
self.registered_on = datetime.datetime.now()
self.admin = admin
app.py
from flask import Flask, render_template
from flask import request, jsonify, session
from flask.ext.bcrypt import Bcrypt
from flask_sqlalchemy import SQLAlchemy
from models import User
app = Flask(__name__)
db = SQLAlchemy()
POSTGRES = {
'user': 'postgres',
'db': 'postgres',
'host': 'localhost',
'port': '5432',
}
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://%(user)s#%(host)s:%(port)s/%(db)s' % POSTGRES
app.config['SECRET_KEY'] = 'lol'
bcrypt = Bcrypt(app)
db.init_app(app)
#app.route('/api/register', methods=['POST'])
def register():
json_data = request.json
user = User(
email=json_data['email'],
password=json_data['password']
)
try:
db.session.add(user)
db.session.commit()
status = 'success'
except:
status = 'this user is already registered'
db.session.close()
return jsonify({'result': status})
manage.py
from flask_script import Manager
from flask_migrate import Migrate, MigrateCommand
from app import app, db
from models import User
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
#manager.command
def create_admin():
"""Creates the admin user."""
db.session.add(User(email='admin#admin.com', password='admin', admin=True))
db.session.commit()
if __name__ == '__main__':
manager.run()
I have played around with the imports but nothing seems to work, I usually will get a circular import error like this:
Traceback (most recent call last):
File "app.py", line 7, in <module>
from models import User
File "/Users/Rishub/Desktop/apps/topten/models.py", line 3, in <module>
from app import bcrypt, db
File "/Users/Rishub/Desktop/apps/topten/app.py", line 7, in <module>
from models import User
ImportError: cannot import name User
Does anyone know the solution to this?
In addition, if I run python manage.py runserver, my app runs fine so I am curious as to why this works but python app.py does not.
in models.py you are importing:
from app import bcrypt, db
in app.py you are importing models.
from models import User
To fix it restructure the program as shown here: http://flask.pocoo.org/docs/0.12/patterns/sqlalchemy/
create a database.py file with database configs etc.
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
engine = create_engine('sqlite:////tmp/test.db', convert_unicode=True)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()
def init_db():
import models
Base.metadata.create_all(bind=engine)
use this in models.py as
from database import Base
from sqlalchemy import Column, Integer, String
# instead of db.column directly use Column
class User(Base):
and app files as:
from database import init_db
init_db()
from database import db_session
from models import User
#app.route('/api/register', methods=['POST'])
def register():
json_data = request.json
user = User(
email=json_data['email'],
password=json_data['password']
)
db_session.add(user)
db_session.commit()
return jsonify({'result': 'success'})