Experts!
I am a beginner in Flask.
I have any project and it includes some models(already defined).
This is one of my models and these are placed as other files, not in app.py.
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
from sqlalchemy import Column, Integer, SmallInteger, String, Text, Date, Boolean, Float
class CategoryTopicLink(Base):
__tablename__ = 'category_topic_link'
id = Column(Integer, primary_key=True)
category_id = Column(Integer)
topic_id = Column(Integer)
And I am going to migrate these by running app.py.
So I inputted some code in app.py and my app file look at following:
from flask import Flask, jsonify, request, make_response
...
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
CORS(app)
api = Api(app)
db = SQLAlchemy(app)
migrate = Migrate(app, db)
from .models import CategoryTopicLink
........
if __name__=="__main__":
app.run(debug=True,host="127.0.0.1",port="5001")
And To migrate model I commanded
"python3 app.py db init" (but server run)
"python3 app.py db migrate" (also server run, not migrate)
"flask run db init" (error - flask has not db attribute)
"flask run db migrate" (error - flask has not db attribute)
......
Please let me know how to migrate models.
Any help will be appreciated.
Regards, from jis0324!!!
The commands are always in the form
flask db command
Also see the manual
https://flask-migrate.readthedocs.io/en/latest/
Related
I'm currently migrating my Flask app from flask-sqlalchemy 2.5.1 to 3.0.2. The app includes an endpoint that lets the client create a new database file at a selected path. Before the migration, it was achieved by simply setting the path and creating the tables in the following way:
app.config['SQLALCHEMY_DATABASE_URI'] = filepath
db.create_all()
However, the file is no longer automatically created in 3.0.2.
Question
I have been digging through the flask-sqlalchemy and sqlalchemy documentations for the past two days yet I can't find anything that would mention the changed behaviour. Creating the file before setting the config doesn't work either, as the tables are not created and the file size is 0b after calling the endpoint.
How can I create a new sqlalchemy DB file inside of a Flask endpoint?
Below is a minimal reproducible example:
server.py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
TEST_DB_PATH = os.path.join(os.getcwd(), "test.db")
# create the extension
db = SQLAlchemy()
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
# create the app
app = Flask(__name__)
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True
# configure the first SQLite database, in memory
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///"
# initialize the app with the extension
db.init_app(app)
with app.app_context():
db.create_all()
#app.route('/test')
def test():
# configure the second SQLite database, relative to the app instance folder
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + TEST_DB_PATH
db.create_all()
return "OK", 200
if __name__ == '__main__':
app.run()
test_server.py
import server
import os
import pytest
#pytest.fixture(scope="session")
def client():
app = server.app
return app.test_client()
def test_create_db_file(client):
# clean local test.db file if it exists
try:
os.remove(server.TEST_DB_PATH)
except OSError:
pass
ans = client.get("test")
assert ans.status_code == 200, ans.data
# this assertion fails
assert os.path.exists(
server.TEST_DB_PATH), f"DB file created at execution cannot be found at " + server.TEST_DB_PATH
assert os.path.getsize(
server.TEST_DB_PATH) > 0, "Created db file size is 0"
Running the test
py -m pytest .\test_server.py
The assertions fail with flask-sqlalchemy 3.0.2 and pass with 2.5.1.
Environment
Windows 11 x64
flask-sqlalchemy 2.2.2
sqlalchemy 1.4.46
pytest 7.2.0
python 3.9.13
I have a task of updating every single row of a MySQL table but it's super slow. I rarely need to do it and only when I change something fundamental, but I thought this would be a great change to learn about multi threading. However all the examples and tutorials online go over some things and not others and I'm struggling to piece all the information together.
I know I need to make a celery process I just don't know if I'm doing it right. A lot of tutorials talk about dockerizing a redis environment without explaining how to do it so I thought I'd come here for some real human-to-human interaction to maybe help me feel less stupid about this.Here's my code so far
/website/__init__.py
from flask import Flask, appcontext_popped, render_template
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, UserMixin, login_user, login_required, logout_user, current_user
from flask_migrate import Migrate
from flask_wtf import CSRFProtect
import logging
import celery
#Path Math
import sys
import os
from . import config
db:SQLAlchemy = SQLAlchemy()
migrate = Migrate()
csrf = CSRFProtect()
celery: celery.Celery
DB_NAME = "main"
def create_app(name):
#Flask Instance
app = Flask(__name__)
app.config.from_object(config.ProdTestConfig)
# logging stuff
#Database
db.init_app(app)
migrate.init_app(app, db)
csrf.init_app(app)
global celery
celery = make_celery(app)
with app.app_context():
db.create_all()
# Models and Blueprints here
from .helper_functions import migration_handling as mgh
#where you will find the thing I need to run async
app.before_first_request(mgh.run_back_check)
# log manager stuff
#error page handling
return app
def make_celery(app):
celery = celery.Celery(
app.import_name,
backend=app.config['CELERY_RESULT_BACKEND'],
broker=app.config['CELERY_BROKER_URL']
)
celery.conf.update(app.config)
class ContextTask(celery.Task):
def __call__(self, *args, **kwargs):
with app.app_context():
return self.run(*args, **kwargs)
celery.Task = ContextTask
return celery
I've read some other ways seem to fit a bit better like using:
celery = Celery(__name__, broker=Config.CELERY_BROKER_URL, result_backend=Config.RESULT_BACKEND)
Then in create_app() they run celery.conf.update(app.config). The issue with this is that I don't know how to setup a redis server on my linode machine hosting the site and my personal windows machine. I have redis pip installed. This is how the function I'm trying to run async looks:
#celery.task(name='app.tasks.campaign_pay_out_process')
def campaign_pay_out_process():
'''
Process Every Campaigns Pay
'''
campaign: Campaigns
for campaign in Campaigns.query.filter_by():
campaign.process_pay()
db.session.commit()
current_app.logger.info('Done Campaign Pay Out Processing')
I'm running gunicorn off of supervisor because restarting is super easy and ridding my life of super long linux commands to start a process has been great. I know this is the command for celery: celery -A celery_worker.celery worker --pool=solo --loglevel=info and I'd love to know how to include that in my work flow. Here's my supervisor config:
[program:paymentwebapp]
directory=/home/sai/paymentWebApp
command=/home/sai/paymentWebApp/venv/bin/gunicorn --workers 1 --threads 3 wsgi:app
user=sai
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
stderr_logfile=/var/log/paymentwebapp/paymentwebapp.err.log
stdout_logfile=/var/log/paymentwebapp/paymentwebapp.out.log
Here's my flask config right now:
from os import environ, path
from dotenv import load_dotenv
DB_NAME = "main"
class Config:
"""Base config."""
#SESSION_COOKIE_NAME = environ.get('SESSION_COOKIE_NAME')
MAX_CONTENT_LENGTH = 16*1000*1000
RECEIPT_FOLDER = '../uploads/receipts'
IMPORT_FOLDER = 'uploads/imports'
UPLOAD_FOLDER = 'uploads'
EXPORT_FOLDER = '/uploads/exports'
UPLOAD_EXTENSIONS = ['.jpg', '.png', '.pdf', '.csv', '.xls', '.xlsx']
STATIC_FOLDER = 'static'
TEMPLATES_FOLDER = 'templates'
class ProdConfig(Config):
basedir = path.abspath(path.dirname(__file__))
load_dotenv('/home/sai/.env')
env_dict = dict(environ)
FLASK_ENV = 'production'
DEBUG = False
TESTING = False
SQLALCHEMY_DATABASE_URI = environ.get('PROD_DATABASE_URI')
SECRET_KEY = environ.get('SECRET_KEY')
SERVER_NAME = environ.get('SERVER_NAME')
SESSION_COOKIE_SECURE = True
WTF_CSRF_TIME_LIMIT = 600
#Uploads
class DevConfig(Config):
basedir = path.abspath(path.dirname(__file__))
load_dotenv('C:\saiscripts\intercept_branch\Payment Web App Project\.env')
env_dict = dict(environ)
FLASK_ENV = 'development'
DEBUG = True
SQLALCHEMY_DATABASE_URI = environ.get('DEV_DATABASE_URI')
SECRET_KEY = environ.get('SECRET_KEY')
class ProdTestConfig(DevConfig):
'''
Developer config settings but production database server
'''
SQLALCHEMY_DATABASE_URI = environ.get('PROD_DATABASE_URI')
if __name__ == '__main__':
print(environ.get('SQLALCHEMY_DATABASE_URI'))
This is where I copied some code from a tutorial because I'm supposed to make a celery worker:
#!/usr/bin/env python
import os
#from app import create_app, celery
from website import create_app
app = create_app()
app.app_context().push()
from website import celery
I am creating a flask application where I am using the app factory method. I have a file in the application folder __init__.py which has the create_app function with the following code
def create_app(test_config=None):
app = Flask(__name__,instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:#localhost/database'
db = SQLAlchemy(app)
if test_config == None:
app.config.from_pyfile('config.py',silent=True)
else:
app.config.form_mapping(test_config)
from flaskr import models
try:
os.makedirs(app.instance_path)
except OSError:
pass
class User(db.Model):
id = db.Column(db.Integer,primary_key=True)
uname = db.Column(db.String(50))
#app.route('/hello')
def hello():
return json.dumps({'message':'hello','status':True})
#app.route('/getusers')
def getusers():
u = User.query.get(1)
return json.dumps({'uname':u.uname})
return app
What I want is to define the models in a seperate file. How can I do this?
I have tried defining in a seperate file and importing it. But the problem is the model inherits the db.Model which is then not available in the imported file.
Leave the creation of db object outside create_app without passing any app instance and use the SQLAlchemy.init_app method to configure and init. your db object, this way you can import it from any file:
db = SQLAlchemy()
#...
def create_app(test_config=None):
app = Flask(__name__,instance_relative_config=True)
#...
db.init_app(app)
More on this topic can be found at flask's documentation
I've fought with this problem a few hours too. Couldn't fix it until I came to the realization, that I have to return the app inside the app.app_context()
model.py:
from flask_user import UserMixin
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class User(db.Model, UserMixin):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255, collation='NOCASE'), nullable=False,
unique=True)
# ...
__init__.py:
from flask import Flask
from flask_migrate import Migrate
def create_app(test_config=None):
app = Flask(__name__, instance_relative_config=True)
app.config.from_pyfile('config.py', silent=True)
migrate = Migrate()
from appname.model import db
db.init_app(app)
migrate.init_app(app, db)
with app.app_context():
# Create all database tables
db.create_all()
import appname.routes
# Apply the blueprints to the app
from appname import bp1, bp2
appname.register_blueprint(bp1.bp)
appname.register_blueprint(bp2.bp)
return app
Run with:
cd ~/Folder/Webapp
. appname/bin/activate
export FLASK_APP=appname
export FLASK_ENV=development
flask run
(in Linux terminal)
or create this file and run it in python shell:
from appname import create_app
if __name__ == '__main__':
app = create_app()
app.run(debug=True)
I'm reading DATABASE_URL from env variable in uwsgi file. My django ORM connection is working with % in password but when I try to connect with sqlalchemy it is not working.
from sqlalchemy import orm, create_engine, MetaData
from app.settings import DATABASES
from urllib import quote_plus
con = "mysql+pymysql://{0}:{1}#{2}:{3}/{4}".format(
DATABASES['default']['USER'],
DATABASES['default']['PASSWORD'],
DATABASES['default']['HOST'],
DATABASES['default']['PORT'],
DATABASES['default']['NAME']
)
engine = create_engine(
con,
echo=False,
pool_recycle=1800,
max_overflow = 250,
pool_size=200
)
I even tried quote_plus but it did not worked.
This does not works
mysql+pymysql://api:#>J.6D%qhZ#localhost:3306/table_tmp
This works
mysql+pymysql://api:#>J.6DqhZ#localhost:3306/table_tmp
When I use same password with % via ipython it works but via env variable in uwsgi.ini file it doesn't
I've a question related to Flask-migrate.
I'm creating a set of web services with Flask. I've split each web service in his own package in a python application.
The application structure look like this:
MyApp
WS1
models.py
WS2
models.py
CommonPackage
models.py
How can I import all the modules and init the db? I've tried to import them all manually but is not working.
I know that it works if I import the "app" from WS1 or Ws2 separately, but I would like to do this in a single operation, is this possible?
Here you can find the code for Flask-migrate:
#!virtualenv/bin/python
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate, MigrateCommand
from flask_script import Manager
from config import SQLALCHEMY_DATABASE_URI
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)
from WS1.models import Class1, Class2, Class3 <--- This is not importing
from WS2.models import Class4, Class5, Class6 <--- This is not importing
if __name__=='__main__':
manager.run()
This is the modules where I initialize SQLAlchemy session:
from sqlalchemy import create_engine
from sqlalchemy.orm import scoped_session, sessionmaker
from sqlalchemy.ext.declarative import declarative_base
from config import SQLALCHEMY_DATABASE_URI
engine = create_engine(SQLALCHEMY_DATABASE_URI, convert_unicode = True)
db_session = scoped_session(sessionmaker(autocommit=False,
autoflush=False,
bind=engine))
Base = declarative_base()
Base.query = db_session.query_property()
All the models import this module and inherit from Base.
Thanks a lot,
Enrico
When you are defining a custom declarative base you're not really using Flask-SQLAlchemy anymore—and Flask-Migrate reads the models from Flask-SQLAlchemy's internal declarative base. (That is why you have to initialize Migrate with both app and db).
Flask has an answer to the import cycle problem: Most Flask extensions have an .init_app() method to defer initializing the extension where necessary.
In the module where you currently create Base by hand, just do db = SQLAlchemy() and then in your models import db and use db.Models as your declarative base instead of Base. In your app.py, do the following:
from dbpackagename import db
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = SQLALCHEMY_DATABASE_URI
db.init_app(app)