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'.
Related
Problem: I am new to creating a website on the flask and my code is running smoothly without any error, but I can't see the database file on my working directory or in my Project and I dont know what is the reason why the database file is not showing or creating in my directory. Can someone help me?
My directory
Project
|
|__flask-session
|__ST_website
|____flask-session
|____static
|____templates
|______ __init__.py
|______ database.py
|______ primary.py
|______ user_identification.py
|__venv(library root)
|__run.py
(|__ST_database.db # wanted to create)
init.py
import os
from flask_session import Session
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
from datetime import timedelta
# Database
db = SQLAlchemy()
DB_NAME = "ST_database.db"
UPLOAD_FOLDER = 'ST_website/static/csv-files' # Upload Folder
def create_app():
""" Creating an App"""
app = Flask(__name__)
app.config['SECRET_KEY'] = 'hi'
app.config['SQLALCHEMY_DATABASE_URL'] = 'sqlite:///ST_database.db'
app.config["SQLAlCHEMY_TRACK_MODIFICATIONS"] = False # Handling Warnings
app.config["SESSION_TYPE"] = "filesystem"
app.permanent_session_lifetime = timedelta(minutes=20) # How long will the data last.
db.init_app(app)
Session(app)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER # Upload file
# file name Variable name
from .primary import primary
from .user_identification import user_identi
# Registering Blueprints
app.register_blueprint(user_identi, url_prefix='/')
app.register_blueprint(primary, url_prefix='/')
login_man = LoginManager()
login_man.login_view = 'user_identi.login' # Directing here if the user is not log-in
login_man.init_app(app) # telling Login manager what app will use
from .database import User, UserData
create_database(app)
#login_man.user_loader
def load_user(id):
"""Load the user"""
return User.query.get(int(id)) # automatically get the Primary Key
return app
def create_database(application):
db_filename = f'ST_website/{DB_NAME}'
if not os.path.exists(db_filename):
db.create_all(app=application)
print('Created Database!')
database.py
from . import db
from flask_login import UserMixin
from sqlalchemy.sql import func
class User(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150), unique=True)
name = db.Column(db.String(150))
password = db.Column(db.String(150))
user_data = db.relationship('UserData')
class UserData(db.Model):
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(150))
filename = db.Column(db.String(150))
filepath = db.Column(db.String(150))
date_of_upload = db.Column(db.DateTime(timezone=True), default=func.now())
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
run.py
from ST_website import create_app
app = create_app()
print(app)
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
Terminal
D:\Project\venv\lib\site-packages\flask_sqlalchemy\__init__.py:851: UserWarning: Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set. Defaulting SQLALCHEMY_DATABASE_URI to "sqlite:///:memory:".
warnings.warn(
D:\Project\venv\lib\site-packages\flask_sqlalchemy\__init__.py:872:FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning.
warnings.warn(FSADeprecationWarning(
Created Database!
<Flask 'ST_website'>
* Serving Flask app 'ST_website' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: on
* Restarting with stat
D:\Project\venv\lib\site-packages\flask_sqlalchemy\__init__.py:851: UserWarning: Neither SQLALCHEMY_DATABASE_URI nor SQLALCHEMY_BINDS is set. Defaulting SQLALCHEMY_DATABASE_URI to "sqlite:///:memory:".
warnings.warn(
D:\Project\venv\lib\site-packages\flask_sqlalchemy\__init__.py:872:FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future. Set it to True or False to suppress this warning.
warnings.warn(FSADeprecationWarning(
* Debugger is active!
* Debugger PIN: 412-312-823
Created Database!
<Flask 'ST_website'>
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://192.168.1.10:5000/ (Press CTRL+C to quit)
In your init.py file, please change this line.
app.config['SQLALCHEMY_DATABASE_URL'] = 'sqlite:///ST_database.db'
to,
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///ST_database.db'
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/
I'm attempting to run flask migrate db in my working directory, and it does not use the model I defined in models.py
Here's the code.
models.py
import sys
sys.path.append("../")
from Talks2 import db
class Talk(db.Model):
presenter = db.Column(db.Text())
talkType = db.Column(db.Text())
desc = db.Column(db.Text(), primary_key=True)
link = db.Column(db.Text())
time = db.Column(db.Integer())
def __repr__(self):
return "Presenter: {}\nType: {}\nDescription:\n{}\nLink: {}".format(self.presenter,self.talkType,self.desc,self.link)
routes.py
import sys
sys.path.append("../")
from flask import Flask, request, render_template
from Talks2 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 Talks2 import models
#app.route("/")
def index():
return render_template("index.html")
#app.route("/add", methods=["POST"])
def add():
person = request.form["presenter"]
ttype = request.form["type"]
desc = request.form["desc"]
link = request.form["link"]
print(person, file=sys.stderr)
print(ttype, file=sys.stderr)
print(desc, file=sys.stderr)
print(link, file=sys.stderr)
return render_template("index.html")
if __name__ == "__main__":
app.run()
What do I need to change for it to correctly generate the script?
You are importing db from Talks2.py in models.py file and again in routes.py declaring again.
You haven't shared the code of Talks2.py file. What I am suspecting is you are declaring app and db object multiple times and replacing it with others.
Just do import in the proper way and your model will be detected by the flask.
The simplest solution is to declare app & db in Talks2.py, then import both in models.py and then from models.py import app & db in routes.py. This will resolve your problem.
Also, it should be flask db migrate instead of flask migrate db.
For more information refer to these commands:
To create a migration repository:
flask db init
To Generate Migration Script (Make sure to reviewed and edited, as Alembic currently does not detect every change you make to your models)
flask db migrate
To apply the migration to the database
flask db upgrade
To see all the commands that are available run this command:
flask db --help
For more info refer this official doc.
Let me know if this didn't help.
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
I'm trying to do unit testing of my Flask web app. I'm use a pattern I saw in a Udemy class on Flask and a pattern similar to the Flask Mega-Tutorial online (http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-vii-unit-testing). The problem I'm having is that the test does not actual create it's own database -- rather it uses the production database and messes it up.
Here's what tests.py script looks like:
import os,sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
basedir = os.path.abspath(os.path.dirname(__file__))
import unittest
from myapp import app, db
from user.models import User
class UserTest(unittest.TestCase):
def setUp(self):
self.db_uri = 'sqlite:///' + os.path.join(basedir, 'test.db')
app.config['TESTING'] = True
app.config['WTF_CSRF_ENABLED'] = False
app.config['SQL_ALCHEMY_DATABASE_URI'] = self.db_uri
self.app = app.test_client()
db.create_all()
def tearDown(self):
db.session.remove()
db.drop_all()
def test_models(self):
#Create a customer user
user = User("John Doe", "jdoe#jdoe.com", "jdoe", "password", is_consultant=False)
db.session.add(user)
db.session.commit()
#Create 2 consultant users
user1 = User("Jane Doe", "janedoe#gg.com", "janedoe", "password", is_consultant=True)
db.session.add(user1)
user2 = User("Nikola Tesla", "nikola#tesla.com", "nikola", "password", is_consultant=True)
db.session.add(user2)
db.session.commit()
#Check that all users exist
assert len(User.query.all()) is 3
My app init is in the same folder and looks like so:
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.migrate import Migrate
from flask.ext.login import LoginManager
app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
# flask-login extension setup
login_manager = LoginManager()
login_manager.init_app(app)
# migration setup
migrate = Migrate(app, db)
from user import views
I don't understand what is going on. It never creates the test.db SQLite database. It always creates the app.db production database. And if it's there, it totally messes up the database is there. Afterwards if I do python manage.py runserver -- it doesn't work anymore. It says table not found. Because the teardown dropped all the tables. What is going on? And how do I fix it?
Omigod I figured it out. I was setting the wrong key for the database URI. It should be: app.config['SQLALCHEMY_DATABASE_URI'] = self.db_uri.
So everything is fine. Just do:
class UserTest(unittest.TestCase):
def setUp(self):
self.db_uri = 'sqlite:///' + os.path.join(basedir, 'test.db')
app.config['TESTING'] = True
app.config['WTF_CSRF_ENABLED'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = self.db_uri
self.app = app.test_client()
db.create_all()
and everything works as intended.
I checked what was going on by putting a break-point in the tests and seeing what app.config was -- and I saw that there was both a SQL_ALCHEMY_DATABASE_URI key (which doesn't do anything and I was setting) and a SQLALCHEMY_DATABASE_URI key (this is the one that matters).