Flask tutorial: AttributeError teardown_appcontext - python

I'm a beginner of Python and Flask.
I was going through Flask tutorial up to "Define and Access the Database" section.
Wrote up all codes, saved, and did below on Windows command prompt.
flask init-db
However, got received the error on the command prompt as follows.
AttributeError: 'ellipsis' object has no attribute 'teardown_appcontext'
I doublechecked the codes to confirm it's written exactly in a way that tutorial specifies and it actually worked fine until the previous section.
Searched through Stackoverflows if there is any similar questions, but ended up not finding out a clear cause.
Any advises? Thank you very much for your support.
--Additions--
Thanks Joost. Here is what I did.
Files layout image link
__init__.py
import os
from flask import Flask
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# Load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# Load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance floder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
#app.route('/hello')
def hello():
return 'Hello, World!'
def create_app():
app = ...
# existing code omitted
from . import db
db.init_app(app)
return app
db.py
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
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 exisitng 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)
schema.sql
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
author_id INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
body TEXT NOT NULL,
FOREIGN KEY (author_id) REFERENCES user (id)
);
And finally I did on the command prompt:
set FLASK_APP=flaskr
set FLASK_ENV=development
flask init-db
However it returned like this.
Any advises?
Thank you very much.

You defined create_app() twice. To solve your problem, make the following change in your __init__.py files:
import os
from flask import Flask
def create_app(test_config=None):
""" Application factory function """
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
#app.route('/hello')
def hello():
return 'Hello, World! Now We are Introducing Mr. Narendra Singh Parihar.THE BOSS !!'
from . import db
db.init_app(app)
return app

Actually the problem is in your init.py
I removed the second create_app() from your init file and edited it like below remember the app factory need to know where your db.py is while creating the app
import os
from flask import Flask
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# Load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# Load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance floder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
#app.route('/hello')
def hello():
return 'Hello, World!'
from . import db
db.init_app(app)
return app

you don't replace the existing code with the new proposed one,
but you add to it,
so for example :
def create_app():
app = ...
# existing code omitted
from . import db
db.init_app(app)
return app
should be translated in your code by adding the two new lines :
from . import db
db.init_app(app)
to what's already there so far in the function, just before the last line.
return app
which should translate as other answers mentioned :
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# Load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# Load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance floder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
#app.route('/hello')
def hello():
return 'Hello, World!'
from . import db
db.init_app(app)
return app

Related

Flask Tutorial __init__.py content

I'm a beginner in Python and flask. I am going through the Flask tutorial up to Blog Blueprint section.
I would like to know the meaning of app = ...
int the following code:
def create_app():
app = ...
# existing code omitted
from . import blog
app.register_blueprint(blog.bp)
app.add_url_rule('/', endpoint='index')
return app
In a real Flask application ... would be replaced by a call to the Flask constructor, with the desired configurations.
Check this example on how to initialize a Flask app: https://flask.palletsprojects.com/en/2.1.x/tutorial/factory/
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
# load the instance config, if it exists, when not testing
app.config.from_pyfile('config.py', silent=True)
else:
# load the test config if passed in
app.config.from_mapping(test_config)
# ensure the instance folder exists
try:
os.makedirs(app.instance_path)
except OSError:
pass
# a simple page that says hello
#app.route('/hello')
def hello():
return 'Hello, World!'
return app

.db file not found Flask SQLite

After executing the code, the database file (here test.db) is not found in the working directory or the home directory. The Python-flask code is given below. I have seen in the YouTube videos that the .db file is automatically created after the connection is successfully made.
import os
from flask import Flask, render_template, request, redirect
from flask_sqlalchemy import SQLAlchemy
UPLOAD_FOLDER = './uploads'
ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg'}
app = Flask(__name__)
#db_path = os.path.join(os.path.dirname(__file__), 'test.db')
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['SQLALCHEMY_DATABASE_URI']='sqlite:///test.db' #path of the database
app.config['SQLALCHEMY_TRACK_MODIFICATIONS']=False
#initialising the database
db=SQLAlchemy(app)
db.init_app(app)
#create database model
#we will not have to give sql commands, just can be created using class
class exec_members(db.Model):
id=db.Column(db.Integer,primary_key=True) #person id
name=db.Column(db.String(50),nullable=False) #execom member name
postn=db.Column(db.String(100),nullable=False) #position represented by the execom member
twitter=db.Column(db.String(200),nullable=False) #twitter id of the execom member
facebook=db.Column(db.String(200),nullable=False) #facebook id of the execom member
instagram=db.Column(db.String(200),nullable=False) ##instagram id of the execom member
linkedin=db.Column(db.String(200),nullable=False) #linkedin id of the execom member
#img_name=db.Column(db.String(200),nullable=False) #image of the execom member
#app.route("/admin")
def hello_world():
return render_template('admin.html')
#app.route("/",methods=['GET'])
def home():
return render_template('home.html')
#app.route("/details",methods=['POST'])
def details():
pname=request.form['name']
post=request.form['post-name']
twitterid=request.form['twitter']
facebookid=request.form['facebook']
instagramid=request.form['instagram']
linkedinid=request.form['linkedin']
try:
db.session.add(exec_members(name=pname))
db.session.add(exec_members(postn=post))
db.session.add(exec_members(twitter=twitterid))
db.session.add(exec_members(facebook=facebookid))
db.session.add(exec_members(instagram=instagramid))
db.session.add(exec_members(linkedin=linkedinid))
except:
print("Error adding to database!")
return redirect('/admin')
#########################error uploading files to the database
#print(name, post, twitter, facebook, instagram, linkedin)
Plus, there is no error returned after executing the code.
No, the flask-sqlalchemy will not create a database itself. You should create it yourself.
Create the path to the directory you want the database file to be located:
basedir = os.path.abspath(os.path.dirname(__file__))
# this will be the top-level directory
Add your database configurations:
SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or \
'sqlite:///' + os.path.join(basedir, 'test.db')
SQLALCHEMY_TRACK_MODIFICATIONS = False
If the DATABASE_URL variable is not found in the environment, then a file called test.db will be created in the top level directory.
When you run your migrations, then the test.db file will be automatically created, as you have 'heard'.

First time creating a website with Flask, I keep coming up with 'Error: No such command 'init-db' when creating a database

I'm following this tutorial, but have still managed to mess it up. Go figure.
Done everything up to the third page where we create the database. I know init-db is the correct format, I have installed flask within the venv, and I have no idea where I went wrong.
Edit: I have done the exports
db.py
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
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)
init.py
import os
from flask import Flask
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
if test_config is None:
app.config.from_pyfile('config.py', silent=True)
else:
app.config.from_mapping(test_config)
try:
os.makedirs(app.instance_path)
except OSError:
pass
#app.route('/hello')
def hello():
return 'Hello World'
from . import db
db.init_app(app)
return app
and schema.sql
DROP TABLE IF EXISTS user;
DROP TABLE IF EXISTS post;
CREATE TABLE user (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT UNIQUE NOT NULL,
password TEXT NOT NULL
);
CREATE TABLE post (
id INTEGER PRIMARY KEY AUTOINCREMENT,
author_id INTEGER NOT NULL,
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
title TEXT NOT NULL,
body TEXT NOT NULL,
FOREIGN KEY (author_id) REFERENCES user (id)
);
complete error code:
(venv) root#pi:/home/pi/flaskr# flask init-db
Usage: flask [OPTIONS] COMMAND [ARGS]...
Try 'flask --help' for help.
Error: No such command 'init-db'.
So.. This took a while for me to recreate, however I have figured it out. You are in the wrong directory in your terminal. flask init-db needs to be ran from pi not flaskr... this is assuming that your venv environment is in pi.

Access Flask-SQLAlchemy database outside of view functions

I have created a small Flask application which stores its data in an sqlite database that I access via flask-sqlalchemy.
However, when I run it, I get the following error:
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.
I have debugged my application and now know that this error stems from these two functions:
def user_exists(email):
if User.query.filter_by(email = email).count() == 0:
return False
else:
return True
def get_user(email):
user = User.query.filter_by(email = email).first()
return user
Now I am wondering: Is it impossible to access the database via flask-sqlalchemy outside of view functions?
For further context, I added the files in which I configure my flask app:
presentio.py
from app import create_app
app = create_app(os.getenv("FLASK_CONFIG", "default"))
app/init.py
from flask_mail import Mail
from flask_sqlalchemy import SQLAlchemy
from config import config
mail = Mail()
db = SQLAlchemy()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
mail.init_app(app)
db.init_app(app)
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint, url_prefix = "/auth")
from .text import text as text_blueprint
app.register_blueprint(text_blueprint, url_prefix = "/text")
return app
You need to give the flask app a context after you create it.
This is done automatically in view functions, but outside those, you need to do this after you create the app:
app.app_context().push()
See the docs: https://flask-sqlalchemy.palletsprojects.com/en/2.x/contexts/

Where is the name of a database file to be created specified?

From http://flask.pocoo.org/docs/1.0/tutorial/database/
import sqlite3
import click
from flask import current_app, g
from flask.cli import with_appcontext
def get_db():
if 'db' not in g:
g.db = sqlite3.connect(
current_app.config['DATABASE'],
detect_types=sqlite3.PARSE_DECLTYPES
)
g.db.row_factory = sqlite3.Row
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)
...
def create_app():
app = ...
# existing code omitted
from . import db
db.init_app(app)
return app
Run the init-db command:
flask init-db
Initialized the database.
There will now be a flaskr.sqlite file in the instance folder in
your project.
I am surprised that flaskr.sqlite seems created without being specified any where. How it is specified to be created?
How is the name of the file flaskr.sqlite specified to sqlite3 when creating the file?
If using sqlite directly without flask, how can I create such a file named flaskr.sqlite?
Thanks.
See the previous page of the Tutorial, Application Setup, where app.config.from_mapping() happens.

Categories

Resources