I was working on my school project which required me to develop an API on Flask. I was using MySQL with Flask SQLAlchemy. After I finished the project I haven't touched it in a month. When I came back and tried to run it I found out that it doesn't create tables on its own.
What I checked:
MySQL user has all permitions
App does connect to the database
Every model has table name defined
app.py file:
import logging
from os import environ
from flask import Flask
from flask_cors import CORS
from flask_restful import Api
from flask_sqlalchemy import SQLAlchemy
from config import DevConfig, ProdConfig
db = SQLAlchemy()
def create_app():
from resources import Area, Map, Ping, SensorData
env = environ.get('ENVIRONMENT')
if env == 'DEVELOPMENT':
Config = DevConfig
else:
Config = ProdConfig
app = Flask(__name__)
app.config.from_object(Config())
CORS(app)
logging.basicConfig(
filename='app.log',
level=logging.INFO
)
api = Api(app)
api.add_resource(Area, '/area')
api.add_resource(Map, '/map')
api.add_resource(SensorData, '/api/v1/saveSensorData')
api.add_resource(Ping, '/ping')
db.init_app(app)
with app.app_context():
from models import AreaModel, SensorDataModel
db.create_all()
return app
if __name__ == '__main__':
app = create_app()
app.run(host='0.0.0.0', port=8080)
One of the models:
from app import db
from datetime import datetime
class AreaModel(db.Model):
__tablename__ = 'area_records'
id = db.Column(
db.Integer,
primary_key=True
)
aqi = db.Column(
db.Integer,
)
latitude = db.Column(
db.String(16),
)
longitude = db.Column(
db.String(16),
)
created = db.Column(
db.DateTime,
default=datetime.now()
)
I found a solution, but not an answer. For some reason, when I run app.py directly using python app.py it won't create any tables. But when I created run.py with this code:
from app import create_app
app = create_app()
app.run(host='0.0.0.0', port=8080)
It worked! I hope someone can explain it but I'm really happy I got the solution.
Related
i have created app.py
and tables.py
which are the main app and a file used to define the tables of a database [database.db] respectively.
I cannot create tables in the database.db, what could be the problem?
Code for both is given below
#app.py
from flask import Flask, render_template, request, session, redirect
from tables import db
from flask_session import Session
app = Flask(__name__)
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
db.init_app(app)
#app.before_first_request
def create_tables():
db.create_all()
#app.route("/")
def home():
return render_template("register.html")
#tables.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class users (db.Model):
users_key = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(21), nullable=False)
email = db.Column(db.String(31), nullable=False, unique=True)
password = db.Column(db.String(61), nullable=False)
i expected to get tables in the database.db file which is located in the same directory as the app.py file. i could not add any tables though.
You have to create database context and initialize it.
with app.app_context():
db.create_all()
Also make sure to import the Flask module from the flask package and SQLAlchemy from the flask_sqlalchemy package in tables.py.
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///database.db'
db = SQLAlchemy(app)
I am trying to build an API using Flask. For database actions I use flask_sqlalchemy.
In my main file, the flask app is initalized. I pass the resulting instance to another file where the configuration is set and to my database module that handles database operations.
main.py:
app = flask.Flask(__name__) # initialize flask app
#initialize modules with app
config.init(app)
database.init(app)
The problem is, the relations I use in the database are in a seperate file and it needs the db object to declare the classes for ORM.
My idea was to declare db and initialize it later in an init function, but that doesn't work in this case, because the db object is undefined when the pythonfile is loaded by an import.
relations.py
db: SQLAlchemy
def init(db):
Relations.db = db
class Series(db.Model):
"""Representation of a series
"""
id = db.Column(db.String(255), primary_key=True)
title = db.Column(db.String(255))
class User(db.Model):
"""Representation of a user
"""
id = db.Column(db.INT, primary_key=True)
name = db.Column(db.String(255))
class Subscription(db.Model):
"""Representation of a subscription
"""
series_id = db.Column(db.INT, primary_key=True)
user_id = db.Column(db.String(255), primary_key=True)
My database module uses the way and it works fine(init.py file):
db: SQLAlchemy
def init(app):
database.db = SQLAlchemy(app)
# handle database operations...
One approach to solve the issue is just using another instance in the relations.py like that:
app = flask.Flask(__name__)
db = SQLAlchemy(app)
# declare classes...
I tried it out and it workes, but that is not a nice way to solve this and leads to other problems.
Importing it from main does also not work because of circular import.
I have no idea how to smoothly solve this without removing modularization. I would be thankful for any inputs. If I should add any further information, just let me know.
I would create the app variable in your main.py file but leave out the initializing part. From there you call a function from init.py to basically set up the database. That is what I did for my last flask project.
Main.py:
from init import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
Init.py:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
DB_NAME = "database.db"
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = f'sqlite:///{DB_NAME}'
db.init_app(app)
create_database(app)
#Other operations ...
return app
Relations.py
from init import db
#all your classes ...
db.create_all()
So now you can import the db object to your relations.py file from the init.py.
With Flask SQL Alchemy, I am using the Chinook sqlite db.
sqlalchemy.exc.ArgumentError: Mapper mapped class PlayLists->playlists could not assemble any primary key columns for mapped table 'playlists'
My code is like this. "app/init.py"
from flask import Flask
from config import app_config
from flask_sqlalchemy import SQLAlchemy
from flask_bootstrap import Bootstrap
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__, instance_relative_config=True)
app.config.from_object(app_config[config_name])
app.config.from_pyfile('config.py')
db.app = app
db.init_app(app)
db.Model.metadata.reflect(db.engine)
Bootstrap(app)
from app import models
return app
The app/model.py
from app import db
class PlayLists(db.Model):
__tablename__ = db.Model.metadata.tables['playlists']
What am I doing wrong?
In your Playlists class you are assigning db.Model.metadata.tables['playlists'] to __tablename__ . However, db.Model.metadata.tables['playlists'] returns an object of class 'sqlalchemy.sql.schema.Table'. You should instead assign it to a string with the name of the table, as in:
app/model.py
from app import db
class PlayLists(db.Model):
__tablename__ = 'playlists'
This example works for me, returning the column names of the reflected database:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.secret_key = 'SUPERSECRET'
app.config['SQLALCHEMY_DATABASE_URI'] = ''mysql+pymysql://user:pass#localhost:port/db''
db = SQLAlchemy(app)
db.init_app(app)
db.Model.metadata.reflect(db.engine)
class User(db.Model):
__tablename__ = "users"
#app.route("/")
def hello():
user = User()
table_columns = str(user.__table__.columns)
return table_columns
if __name__ == "__main__":
app.run()
I am new to deploying to aws as well as flask. Basically I have a simple Flask app but every time I make a change and deploy the new code to aws elastic beanstalk, the db gets reset.
from dateutil import parser
from datetime import datetime
from flask import Flask, request, jsonify
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_cors import CORS
import os
application = app = Flask(__name__)
basedir = os.path.abspath(os.path.dirname(__file__))
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'db.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
ma = Marshmallow(app)
cors = CORS(app)
#app.route('/')
def hello():
return 'hello'
.
.
.
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String)
weight = db.Column(db.Float)
workouts = db.relationship('Workout', backref='user', lazy=True)
def __init__(self, name, weight):
self.name = name
self.weight = weight
class UserSchema(ma.Schema):
class Meta:
fields = ('id', 'name', 'weight')
user_schema = UserSchema(strict=True)
users_schema = UserSchema(many=True, strict=True)
.
.
.
db.create_all()
if __name__ == '__main__':
app.run(debug=True)
I expect that each time I
eb deploy flask-env my db wouldnt get reset but it does. For instance if i create a user and then later change something in the code and deploy, that user is gone.
You should:
Create an EBS Volume
Load the database into that volume
Attach the EBS Volume to your Beanstalk app with an .ebextension. An example can be found here.
With all that being said, this is not a highly available, well architected solution and will deteriorate at scale rapidly.
You will want to replace SQLite with an RDS instance at some point in the future before it becomes a problem.
I'm building a Flask app with Flask-SQLAlchemy and I'm trying to write a script that will create a Sqlite3 database without running the main application. In order to avoid circular references, I've initialized the main Flask app object and the SQLAlchemy database object in separate modules. I then import and combine them in a third file when running the app. This works fine when I'm running the app, as the database is built and operates properly when create rows and query them. However, when I try to import them in another module, I get the following error:
RuntimeError: application not registered on db instance and no applicationbound to current context
My code looks like the following:
root/create_database.py
from application.database import db
from application.server import app
db.init_app(app)
db.create_all()
root/run.sh
export FLASK_APP=application/server.py
flask run
root/application/init.py
from database import db
from server import app
db.init_app(app)
from routes import apply_routes
apply_routes(app)
root/application/database.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
root/application/server.py
from flask import Flask
import os
app = Flask(__name__)
path = os.path.dirname( os.path.realpath(__file__) )
database_path = os.path.join(path, '../mydb.sqlite')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + database_path
root/application/models/init.py
from user import User
root/application/models/user.py
from application.database import db
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
password = db.Column(db.String(120))
def __init__(self, username, password):
self.username = username
self.password = password
In my create_database.py script I'm trying to make sure that the SQLAlchemy db instance is configured with the config details from the app object, but it doesn't seem to be connecting for some reason. Am I missing something important here?
You either have to create a request or you have to create the models with sqlalchemy directly. We do something similar at work and chose the former.
Flask lets you create a test request to initialize an app. Try something like
from application.database import db
from application.server import app
with app.test_request_context():
db.init_app(app)
db.create_all()