Cannot Create tables in a database using SQLAchemy - python

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)

Related

NameError: name 'app' is not defined In Python

I am new to flask and i have been struggling to create an sqlite database but whenever i run the from app import db I get the error message:
NameError: name 'app' is not defined
This is my code:
from flask import Flask, render_template
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
app = Flask(__name__)
db = SQLAlchemy()
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db.init_app(app)
class Todo:
id = db.Column(db.Integer(), primary_key=True)
content = db.Column(db.String(length=300), nullable=False)
date_created = db.Column(db.DateTime, default=datetime.utcnow)
def __repr__(self):
return '<Task %r>' % self.id
#app.route('/')
def index():
return render_template('index.html')
if __name__ == "__main__":
app.run(debug=True)`
The image below is my directory structure. I don't know if it has anything to do with it: Image of directory structure
I tried import db from app so that I will create the db file.
First u need to replace db.init_app(app) with db = SQLAlchemy(app). The starting code could look like this:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
db = SQLAlchemy(app)
Then after your class Todo:
with app.app_context():
db.create_all()

Flask SQL Alchemy create_all doesn't create any tables

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.

Flask SQL Alchemy reflection could not assemble any primary key

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()

Flask Blueprint setup with SQLAlchemy gives UnboundExecutionError

I am using Flask to build an experimental application using Blueprint. Here is my project's structure:
-myproject/
requirements.txt
run.py
-apps/
-static/
-template/
-database/
__init__.py
views.py
model.py
auth.py
message.py
I init my app in init.py, using blueprint to integrate other parts of the app.
app = Flask(__name__)
from .views import views
from .model import model, db
from .auth import auth, login_manager
db.init_app(app)
app.register_blueprint(views)
app.register_blueprint(model)
app.register_blueprint(auth)
Then in views.py:
from flask import Flask, request, redirect, render_template, session, g, url_for, Blueprint
views = Blueprint('views', __name__)
from sqlalchemy.orm import scoped_session, relation, sessionmaker
# ORM Session
orm_session = scoped_session(sessionmaker())
#views.route('/courses')
def courses():
courses = orm_session.query(Course).order_by('-id')
return render_template('courses.html', courses=courses)
My Course class is defined in model.py:
class Course(db.Model):
__tablename__ = 'course'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(255), nullable=False)
subjects = db.relationship('Subject', secondary='course_subject_link')
students = db.relationship('Student', secondary='course_student_link')
active = db.Column(db.Boolean)
def __repr__(self):
return "<{0}:{1.name}:{1.subjects!r}:{1.students!r}>".format(Course, self)
In template folder, I have put something like {% for course in courses %} and {% set active_page = "courses" %} in the template file. When I run the app, it gives me this error:
UnboundExecutionError: Could not locate a bind configured on mapper Mapper|Course|course, SQL expression or this Session
I did not use Blueprint before so the app used to be able to run. But after I used Blueprint the urls seem to be broken. How can I fix this?
I know what the problem is.
From the hint in the error message I guess that I forget to create_engine and pass the engine to sessionmaker using bind=engine.
Here is the code I changed in views.py:
from os.path import join, dirname
_cwd = dirname(__file__)
engine = create_engine('sqlite:///' + join(_cwd, 'database/courses.sqlite'))
Session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
orm_session = Session()
Here database/courses.sqlite is the location of my database file.

using Flask-Migrate together with Flask-Security

I'm trying to get a basic Flask-Security app working with Flask-Migrate. I have two main py files: app.py and db_migrate.py
app.py:
from flask import Flask, render_template, request, session
from flask.ext.babel import Babel
from flask.ext.mail import Mail
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin
import os
basedir = os.path.abspath(os.path.dirname(__file__)) #should be __ file __ with no spaces
# Create app
app = Flask(__name__)
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'super-secret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'app.db')
app.config['DEFAULT_MAIL_SENDER'] = 'info#site.com'
app.config['SECURITY_REGISTERABLE'] = True
app.config['SECURITY_CONFIRMABLE'] = True
app.config['SECURITY_RECOVERABLE'] = True
app.config.from_object('config.email')
# Setup mail extension
mail = Mail(app)
# Setup babel
babel = Babel(app)
#babel.localeselector
def get_locale():
override = request.args.get('lang')
if override:
session['lang'] = override
rv = session.get('lang', 'en')
return rv
# Create database connection object
db = SQLAlchemy(app)
# Setup Flask-Security
from db_manager import User, Role #THIS IS PROBABLY WRONG!
user_datastore = SQLAlchemyUserDatastore(db, User, Role)
security = Security(app, user_datastore)
#db.create_all()
# Views
#app.route('/')
def home():
return render_template('index.html')
if __name__ == '__main__':
app.run()
db_migrate.py:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin
import os
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'app.db')
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
# Define models
roles_users = db.Table('roles_users',
db.Column('user_id', db.Integer(), db.ForeignKey('user.id')),
db.Column('role_id', db.Integer(), db.ForeignKey('role.id')))
class Role(db.Model, RoleMixin):
id = db.Column(db.Integer(), primary_key=True)
name = db.Column(db.String(80), unique=True)
description = db.Column(db.String(255))
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
password = db.Column(db.String(255))
active = db.Column(db.Boolean())
confirmed_at = db.Column(db.DateTime())
favcolor = db.Column(db.String(255))
roles = db.relationship('Role', secondary=roles_users,
backref=db.backref('users', lazy='dynamic'))
def __str__(self):
return '<User id=%s email=%s>' % (self.id, self.email)
if __name__ == '__main__':
manager.run()
I have run the migration tool to initialize and migrate the db once, to create a new db, and it worked:
python db_manager.py db init
python db_manager.py db migrate
I tried to run app.py. It serves correctly on localhost, but then when I try to log a user in, I get the following OperationalError:
OperationalError: (OperationalError) no such table: user u'SELECT user.id AS user_id, user.email AS user_email, user.password AS user_password, user.active AS user_active, user.confirmed_at AS user_confirmed_at, user.favcolor AS user_favcolor \nFROM user \nWHERE lower(user.email) LIKE lower(?)\n LIMIT ? OFFSET ?' (u'xxx#xxx.com', 1, 0)
Basically, I doubt that I'm creating user_datastore and security correctly, as I probably shouldn't be importing User and Role in that way -- but I'm not sure how to access them properly.
EDIT:
I added this final command, thanks to suggestion:
python db_manager.py db ugrade
But, now I get this error when I try to confirm a user registration via email:
(InvalidRequestError: Object '' is already attached to session '1' (this is '3')
The workflow with Flask-Migrate/Alembic is as follows:
db init
This you do once when you create the migration repository and never again.
db migrate
You run this to generate a migration script. The output of the command tells you where the migration script was created, and shows a summary of what was put in it. Your database has not been modified at this stage.
review the migration script
This is very important. Automatic migrations are not perfect, you have to review the generated script and make any corrections that are necessary.
db upgrade
This applies the migration to your database, effectively making the necessary schema changes.
You can now use your database. When you make more changes to your models return to Step 2 and repeat the cycle.
From your description you maybe missed step 4, the upgrade call.
As a side note, you have some duplication between your two scripts, you should try to consolidate them. Take a look at how people build Flask applications split across multiple modules or packages.

Categories