Flask-SQLAlchemy doesn't create table - python

I am trying to use PostgreSQL with Flask-SQLAlchemy. I made a database named data_collector using pgAdmin4. When I try to create a table it's not getting created. I think the connection to the database is not getting established.
I am trying to run it from cmd as:
from app import db
db.create_all()
from flask import Flask, render_template,request
from flask_sqlalchemy import SQLAlchemy
app=Flask(__name__)
app.config['SQLALCHEMY DATABASE_URI'] = 'postgresql://postgres:postgresql#localhost/data_collector'
db=SQLAlchemy(app)
class Data(db.Model):
__tablename__="data"
id=db.Column(db.Integer,primary_key=True)
email_=db.Column(db.String(120),unique=True)
height_=db.Column(db.Integer)
def __init__(self,email_,height_):
self.email_=email_
self.height_=height_
db.create_all()

You didn't commit to the database after creating the tables.
You can do that by:
with app.app_context():
db.create_all()
db.session.commit()
Do something like this.
from flask_sqlalchemy import SQLAlchemy
from flask import Flask
app = Flask(__name__)
db = SQLAlchemy(app)
# ---snip---
with app.app_context():
db.create_all()
db.session.commit() # <- Here commit changes to database
#app.route("/")
def index():
return "Hello, World!"
This should solve your problem.
If you want to reset(delete) your database then:
with app.app_context():
db.drop_all()
db.session.commit()
Nothing is written or deleted or updated in database unless you commit using
db.session.commit()
If you want to revert the changes before comitting use:
db.session.rollback()

Finally got the solution after alot of Googling.
You must import all the models before calling db.create_all() function like this,
def create_db():
from src import models
db.create_all()
db.session.commit()
I have all my models in single file but if you have different files, make sure to import them all.

Related

Why SQLAlchemy won't commit changes?

I've done this so many times before successfully but all of the sudden I can't seem
to make it work. I'm creating tables in my MySQL database using Flask SQLAlchemy as a middleman.
Also using pymysql adapter.
Can you please check my "plumbing" is correct ?
my init.py :
import werkzeug
werkzeug.cached_property = werkzeug.utils.cached_property
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_bcrypt import Bcrypt
from .config import DevConfig
db = SQLAlchemy()
bcrypt = Bcrypt()
def create_app(script_info=None):
app = Flask(__name__)
app.config.from_object(DevConfig)
bcrypt.init_app(app)
db.init_app(app)
from .flask_app import users_blueprint
app.register_blueprint(users_blueprint)
#app.shell_context_processor
def ctx():
return {'app': app, 'db': db}
return app
models.py:
from project import db, bcrypt
class User(db.Model):
__tablename__ = 'users'
...
...
config.py:
import os
class BaseConfig:
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://mark:supersecret#localhost/database1?charset=utf8mb4' # the "?charset" thingy is there to avoid encoding warnings from SQLAlchemy
SECRET_KEY = 'pythonrocks'
class DevConfig(BaseConfig):
DEBUG = True
class ProdConfig(BaseConfig):
DEBUG = False
interpreter:
Instance: /home/mark/project/instance
In [1]: db
Out[1]: <SQLAlchemy engine=mysql+pymysql://mark:***#localhost/database1?charset=utf8mb4>
In [2]: db.create_all()
In [3]: db.session.commit()
I get no error output. The tables are just not being created on commit.
mysql> show tables;
Empty set (0.00 sec)
How can I check what's causing this ? The dev server is running.
You're not importing your models before calling db.create_all() - SQLAlchemy simply doesn't know about your models - and thus can't create the tables.
Import it first, then call db.create_all() and db.session.commit().

How to define and access the database postgresql like flask sample code

I'm new use python flask, I want connected to postgresql use code like flask sample in this link, but in code sample use sqlite3. I try to search code sample and make me confused because every sample use different approach. This my code run but when use CLI to initialize database error.
Error: No such command "init-db".
My structure file
This my code:
run.py
#run.py
import os
from smart_app import create_app
app = create_app()
if __name__ == '__main__':
app.run()
init.py
#__init__.py
from flask import Flask
def create_app(config_filename=None):
app = Flask(__name__, instance_relative_config=True)
# load default configuration
app.config.from_object('config.default')
# load the configuration from the instance folder
app.config.from_pyfile('config.py')
# Load the file specified by the APP_CONFIG_FILE environment variable
# Variables defined here will override those in the default configuration
app.config.from_envvar('APP_CONFIG_FILE')
# Connect to database
from . import db
db.init_app(app)
return app
db.py
db.py
import click
from flask import current_app, g
from flask.cli import with_appcontext
from flask_sqlalchemy import SQLAlchemy
# db = SQLAlchemy()
def get_db():
if 'db' not in g:
g.db = SQLAlchemy()
return g.db
def close_db(e=None):
db = g.pop('db', None)
if db is not None:
db.close()
def init_db():
db = get_db()
with current_app.open_resource('schema.sql') as f:
db.executescript(f.read().decode('utf8'))
#click.command('init-db')
#with_appcontext
def init_db_command():
"""Clear the existing data and create new tables."""
init_db()
click.echo('Initialized the database')
def init_app(app):
app.teardown_appcontext(close_db)
app.cli.add_command(init_db_command)
If you familiar with SQL, use the psycopg2 to connect to your postgresql database.
Or if you want use ORM to operate the database in flask, you can use flask_sqlalchemy.

Registering sqlalchemy extension with current application using init_app()

I'm trying to run an existing app in a new environment. The app ran fine in a previous environment, but when I run it locally it refuses to connect with my DB.
AssertionError: The sqlalchemy extension was not registered to the current application. Please make sure to call init_app() first.
Where I'm confused is that this exact code worked in a previous environment. It's asking me to call init_app() but, from my understanding, that's only if there are multiple apps, which there aren't.
In debugging mode, the app does recognize the object i.e.
>>> type(Candidate)
<class 'flask_sqlalchemy.model.DefaultMeta'>
I am unclear how and where to incorporate app_init() into my code. I have tried...
db = SQLAlchemy(app)
db.init_app(app)
but this didn't have any impact.
Folder structure...
app
- static folder
- templates folder
- _init_.py
- config.py
- views.py
- run.py
- Procfile
You could try following code and structure in init.py
db = SQLAlchemy()
def create_app():
app = Flask()
db.init_app(app)
from user_model import User
with app.app_context():
db.create_all()
The problem was that there was legacy code that was supposed to be removed. I was initializing an app twice by accident.
Instead of creating init.py, why don't you import db directly from models
The code below shows my models.py with table students
from flask import Flask,session
from flask_sqlalchemy import SQLAlchemy
#initialize this two objects below app and db parameters so that app.py will have the same db session.
#then in app.py add from models import db
#finally add db.init_app(app) at the bottom of app.py or run.py
app = Flask(__name__)
db = SQLAlchemy(app)
class Students(db.Model):
id = db.Column('student_id', db.Integer, primary_key = True)
name = db.Column(db.String(50))
email = db.Column(db.String(50))
def __repr__(self):
return '<Student {}>'.format(self.email)
Then in your app.py or run.py
You will have to make an import for db
from models import db
Your assertion error for sql-alchemy can be mitigate by moving the two following line of code
immediately after this line of code towards the bottom
if __name__ == '__main__':
hence the code will become like below and your application will run without issue
if __name__ == '__main__':
#create table
db.create_all()
db.init_app(app)
# remember to turn app debug by setting it to false in production
app.run(debug=True)

SQLAlchemy NameError: Name 'db' is not defined (?)

I am working on a Udemy course using flask to record heights. I am at the point where we are using PostgreSQL, and I have it installed, and I have his code copied exactly:
from flask import Flask, render_template, request
from flask.ext.sqlalchemy import SQLAlchemy
app=Flask(__name__)
app.config(['SQLALCHEMY_DATABASE_URI']='postgresql://postgres:password
#localhost/height_collector')
db=SQLAlchemy(app)
class Data(db.Model):
__tablename__='data'
id=db.Column(db.Integer, primary_key=True)
email_=db.Column(db.String(120), unique=True)
height_=db.Column(db.Integer)
def __init__(self, email_, height_):
self.email_=email_
self.height_=height_
#app.route("/")
def index():
return render_template("index.html")
#app.route("/success", methods=["post"])
def success():
if request.method=='POST':
email=request.form['email_name']
height=request.form['height_name']
print(height,email)
return render_template("success.html")
if __name__=='__main__':
app.debug=True
app.run()
Problem comes into play, when he says to run python in a virtual env, and then enter :db.create_all() to create a database in PostgreSQL and I get this error :
File <'stdin'>, line 1 in
NameError: Name 'db' is not defined
Not sure how to proceed, any input would be appreciated.
you can make a db.py where you can store the code db = SQLAlchemy(). Then import in in app.py. now you can able to call db. or just remove APP in db=SQLAlchemy(app)
I think you probably need to run some of the other code first so that you define db and your table schema. Then you can run db.create_all().
from flask import Flask, render_template, request
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config(['SQLALCHEMY_DATABASE_URI'] =
'postgresql://postgres:password#localhost/height_collector')
db = SQLAlchemy(app)
class Data(db.Model):
__tablename__ = 'data'
id = db.Column(db.Integer, primary_key=True)
email_ = db.Column(db.String(120), unique=True)
height_ = db.Column(db.Integer)
def __init__(self, email_, height_):
self.email_ = email_
self.height_ = height_
db.create_all()
I just faced this error and it is because I didn't import db before calling the db function. If you're running in terminal, 'from yourappname import db' and any other functions you are running.
//IN TERMINAL
from yourappname import db
Start python shell by running the command python. Then import db to define it:
from main import db
db.drop_all()
db.create_all()
You need to set the FLASK env variable.
create a .flaskenv file in the top directory of your project
Add this to your .flaskenv file:
export FLASK_APP=myappfile.py
Install dotenv to your environment
pip install python-dotenv
Now if you run the app it should pick up your env variable.
Type the Following and it will work:
cd flask-app
venv\scripts\activate
python3
from app import db
db.create_all()

Creating a database in flask sqlalchemy

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

Categories