Unable to register a blueprint - flask

CASE UPDATED: 2016-02-10 # 19:45 UTC
I've been researching for several weeks StackOverflow after reading a couple of books related to Flask, I've been testing and trying different configuration options, playing with several codes and finally I'm forced to write asking for help because I'm totally stuck and I can't go ahead alone. I'm sorry about that.
The problem: I'm not able to register a Blueprint correctly in my app. I'm doing something wrong or something is not being done in the right way. Routes that belong to the blueprint are not working.
The error received: Not Found. The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
I'm trying to build an API with Flask and Flask-Restful. I'm new to Flask and new to Flask-Restful too, so, you can imagine how big is my actual learning curve right now.
At present time, my project has this aspect:
/
├── PROJECT
│   ├── __init__.py
│   └── api_1_0
│   ├── __init__.py
│   ├── resources
│   │   ├── __init__.py
│   │   └── users.py
│   └── routes.py
├── config.py
└── run.py
The Plan
The PROJECT (named internally SelfCare) folder will have in the future two or three more packages inside (for web modules belonging to the same project). By now the only one of them is api_1_0.
The idea #1 is to build an API with some basic functionalities. Now, the focus is to present plain messages (return 'hi hi') just to confirm all blocks are working alltogether.
The idea #2 is to build the API as a blueprint inside the SelfCare package. Now i can have only 1 API, but later on i migth have two in parallel running (v1 and v2).
Some days ago i managed to get to work idea 1 but idea 2 is what i cannot get to work. Sorry.
My current files have this contents:
File: run.py
from SelfCare import create_app
app = create_app(config_name='development')
if __name__ == '__main__':
app.run()
File: config.py
import os
class Config:
SECRET_KEY = 'whatever'
APP_DIR = os.path.abspath(os.path.realpath(__file__))
STATIC_DIR = os.path.join(APP_DIR, 'static')
IMAGES_DIR = os.path.join(STATIC_DIR, 'images')
STYLES_DIR = os.path.join(STATIC_DIR, 'styles')
TEMPLATES_DIR = os.path.join(STATIC_DIR, 'templates')
# Method with an application instance (for now, just a bypass)
#staticmethod
def init_app(app):
pass
class DevelopmentConfig(Config):
DEBUG = True
class TestingConfig(Config):
DEBUG = True
class ProductionConfig(Config):
DEBUG = False
# Finally, this is a dead simple configuration dictionary
config = {
# Possible profiles to run under
'development': DevelopmentConfig,
'testing': TestingConfig,
'production': ProductionConfig,
# Default application profile
'default': DevelopmentConfig
}
File: PROJECT/init.py
from flask import Flask, render_template
from flask.ext.moment import Moment
from config import config
moment = Moment()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
# attach routes and custom error pages here
#app.route('/')
def index():
return 'Here we will start'
# HERE IT IS SUPPOSED THE BLUEPRINT IS REGISTERED
# AND ROUTES FROM BLUEPRINT ARE INCORPORATED TO MAIN PROGRAM
from .api_1_0 import api as api_blueprint
app.register_blueprint(api_blueprint)
return app
File: PROJECT/api_1_0/__init__.py
from flask import Blueprint
api = Blueprint('api', __name__)
from .resources import users
File: PROJECT/api_1_0/routes.py
from .api_1_0 import resources
#resources.route('/user', methods=['GET'])
def users():
return 'routes.py en blueprint api_1_0'
File: PROJECT/api_1_0/resources/__init__.py
This file is empty (a constructor).
File: PROJECT/api_1_0/resources/user.py
from flask_restful import Resource, reqparse, abort
# With the following dictionrary I do simulate a database connection
USERS = {
'user1': {'task': 'Build an API'},
'user2': {'task': 'Coordinate development'},
'user3': {'task': 'Build core'},
}
def abort_if_user_doesnt_exist(user):
if user not in USERS:
abort(404, message="User {} doesn't exist".format(user))
parser = reqparse.RequestParser()
parser.add_argument('task')
class User(Resource):
def get(self, user):
abort_if_user_doesnt_exist(user)
return USERS[user]
def delete(self, user):
abort_if_user_doesnt_exist(user)
del USERS[callsign]
return '', 204
def put(self, user):
args = parser.parse_args()
task = {'task': args['task']}
USERS[user] = task
return task, 201
So, routes.py seems not to work, so I cannot go further in the API. I'm stuck, sorry... Probably the error is just in from of me as a big stone and I cannot see it. Sorry.
Any help will be much more than appreciated.
Regards.

You're not registering flask-restful.Api and the REST routes correctly.
Install Flask-DebugToolbar - it will help you in showing your registered routes.
Change your code as follows:
In file config.py add the following two lines to the Config class:
DEBUG_TOOLBAR_ENABLED = True
REST_URL_PREFIX = '/api'
In file: PROJECT/init.py change to:
from flask import Flask, render_template
from flask.ext.moment import Moment
from config import config
moment = Moment()
def create_app(config_name):
app = Flask(__name__)
app.config.from_object(config[config_name])
config[config_name].init_app(app)
try:
from flask_debugtoolbar import DebugToolbarExtension
DebugToolbarExtension(app)
except:
pass
# attach routes and custom error pages here
#app.route('/')
def index():
return render_template('index.html')
# HERE IT IS SUPPOSED THE BLUEPRINT IS REGISTERED
# AND ROUTES FROM BLUEPRINT ARE INCORPORATED TO MAIN PROGRAM
from PROJECT.api_1_0 import api_bp, API_VERSION_V1
app.register_blueprint(
api_bp,
url_prefix='{prefix}/v{version}'.format(prefix=app.config['REST_URL_PREFIX'], version=API_VERSION_V1),
)
# This registers the actual routes
import api_1_0.routes
return app
In file: PROJECT/api_1_0/__init__.py change to:
from flask import Blueprint
import flask_restful
API_VERSION_V1 = 1
api_bp = Blueprint('api', __name__)
api_v1 = flask_restful.Api(api_bp)
Map your resources to routes; in file: PROJECT/api_1_0/routes.py change to:
from PROJECT.api_1_0 import api_v1
from PROJECT.api_1_0.resources.user import User
api_v1.add_resource(User, '/user/<string:user>')
Your routes will now be something like :
http://127.0.0.1:5000/api/v1/user/user1 which returns:
{
"task": "Build an API"
}
http://127.0.0.1:5000/api/v1/user/user2 which returns:
{
"task": "Coordinate development"
}
Note how the routes have been built up; the REST_URL_PREFIX from config plus the version number plus the url in the routes.py add_resource.

It works!
I was confused in the way the blueprints have to be registered. Maybe it was because I'm using PyCharm 5 Pro and, even now that the code is running like a charm, the IDE is telling me in the file PROJECT/api_1_0/___init____.py this message:
api_v1 = flask_restful.Api(api_bp)
api_bp --> Expected type 'Flask', got 'Blueprint' instead.
The inspection detects type errors in function call expressions. Due
to dynamic dispatch and duck typing, this is posible in a limite but
useful number of cases. Types of function parameters can be specified
in docstrings or in Python 3 functon annotations.
No I know I don't have to pay too much attention to this message (or that my IDE is wrongly configured). Many thanks for all.
Regards.

Related

Tests keep using "production" database even after I change sqlalchemy_database_uri in pytest fixture

I have flask application that I am using to get familiar with the flask-sqlalchemy lib and testing using Pytest with fixtures.
I am trying to overwrite the sqlalchemy_database_uri in the app configuration in my test fixtures. But the problem is that when I run them, my tests seem to be working with the "production" database rather than with an ephemeral one. The test record I created for test via fixtures are all in the database that I create in the app initialization.
When I run the test in the example below using pytest from the root folder in that structure. The tests are collected ok, run and pass as expected. But after running the tests a new database called hello.db has been created in the instance folder. What I am trying to do is that the tests use a sqlite database in memory that disapears after the tests run.
How do I go about writing/configuring my tests so that I use an ephemeral sqlite database in memory that is only used for those tests?
# Folder structure
.
├── mini_app
│   ├── __init__.py
│   ├── app.py
│   ├── config.py
│   └── models.py
└── tests
├── __init__.py
└── test_all.py
## app.py
from flask import Flask, request
from flask_sqlalchemy import SQLAlchemy
from mini_app import config
db = SQLAlchemy()
def create_app(cfg= None):
if cfg is None:
cfg = config.Config()
app = Flask(__name__)
app.config.from_object(cfg)
# Init_apps
db.init_app(app)
#app.route("/square")
def square():
"""A view which uses no templates and no database."""
number = int(request.args.get("number", 0))
return str(number ** 2)
return app
## config.py
class Config:
SQLALCHEMY_DATABASE_URI = "sqlite:///hello.db"
## models.py
from mini_app.app import db
class Author(db.Model):
__tablename__ = "authors"
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String)
## test_all.py
import pytest
import mini_app.app
import mini_app.models
#pytest.fixture
def client():
# Prepare before your test
app = mini_app.app.create_app()
app.config["TESTING"] = True
app.testing = True
app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite://"
with app.test_client() as client:
with app.app_context():
mini_app.app.db.create_all()
author1 = mini_app.models.Author(id=1, name="foo")
mini_app.app.db.session.add(author1)
mini_app.app.db.session.commit()
# Give control to the test
yield client
# Cleanup after the test run.
# ... nothing here, for this simple example
def test_square(client):
rv = client.get("/square?number=8")
assert b"64" == rv.data

All routes giving 404 in flask despite the routes.py being successfully imported

I currently working on a flask backend but have hit an issue where all routes return a 404 despite the routes.py apparently running.
routes.py:
import sys, os, json
from flask import Flask, render_template
from flask_cors import CORS, cross_origin
app = Flask(__name__)
app.config.from_pyfile('config.py')
CORS(app)
#app.route('/', endpoint='index')
#app.route('/index', methods=['GET'], endpoint='index')
#cross_origin()
def index():
print('Hello world!', file=sys.stderr)
return render_template('index.html', title='home')
#app.route('/projects', endpoint='projects') # route for projects showcase including json project data loading
#cross_origin()
def projects():
projects = os.path.join(app.static_folder, 'data', 'projects.json')
with open(projects) as pData:
data = json.load(pData)
return render_template('projects.html', title='showcase', data=data)
#app.route('/contact', endpoint='contact')
def contact():
return render_template('contact.html', title='contact')
print('Hello routes!', file=sys.stderr) #testing line
When I launch it the output is this:
* Serving Flask app 'ClayG' (lazy loading)
* Environment: development
* Debug mode: on
Hello routes!
* Restarting with stat
* Debugger is active!
Hello routes!
* Debugger PIN: 274-753-929
* Running on http://127.0.0.1:5000/
the print function at the end of routes.py runs so my app is making it through, but when i visit localhost:5000 I get a 404 with only this in the terminal output
127.0.0.1 - - [05/Feb/2022 17:20:29] "GET / HTTP/1.1" 404 -
The other files and file structure
.
├── ClayG.py
├── .flaskenv
├── app
│ ├── config.py
│ ├── routes.py
│ └── __init__.py
ClayG.py
import os, sys
sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__))))
from app import app
.flaskenv
FLASK_APP=ClayGale
FLASK_ENV=development
init.py
from flask import Flask
from . import routes
app = Flask(__name__)
config.py
class Config:
STATIC_FOLDER = 'static'
TEMPLATES_FOLDER = 'templates'
DEBUG = True
TESTING = True
One thing i've noticed is that adding FLASK_ENV = 'development' to the config class is that it still launches as production and I can only get it to launch in development with the .flaskenv file. I'm unfortunately just stumped as for what to do from here so any wisdom on what to try would be helpful.
You have created two Flask apps. One in routes.py with the endpoints, and a new one in __init__.py which is completely empty. You should use the previously created app in the __init__.py file:
from . import routes
app = routes.app

Is it possible to use FastAPI with Django?

I'm a Django developer and recently stumbled onto the FastAPI framework.
Then I decided to give it a shot. But usually when you talk about building RESTful APIs with Django you usually use the Django Rest Framework (DRF).
Is anybody aware if it is possible to substitute DRF by FastAPI using Django perks, like its ORM, and still have access to all of FastAPI's async features?
Up until now I only found one article on this. But in the process of integration the author lost most of the features of FastAPI.
You can find it here.
In the FastAPI docs, they do mention that it is possible to redirect certain request to a WSGI application here.
Short Answer
Yes it's possible with WSGIMiddleware.
For example, you can use all Django features (yes admin too) with mounting, with this example code.
import os
from importlib.util import find_spec
from configurations.wsgi import get_wsgi_application
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from fastapi.staticfiles import StaticFiles
from api import router
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myapp.settings")
os.environ.setdefault("DJANGO_CONFIGURATIN", "Localdev")
application = get_wsgi_application()
app = FastAPI()
app.mount("/admin", WSGIMiddleware(application))
app.mount("/static",
StaticFiles(
directory=os.path.normpath(
os.path.join(find_spec("django.contrib.admin").origin, "..", "static")
)
),
name="static",
)
Also this one is from WSGIMiddleware documentation, it's a more straight-forward example (This one is for Flask but it demonstrates the same idea.).
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from flask import Flask, escape, request
flask_app = Flask(__name__)
#flask_app.route("/")
def flask_main():
name = request.args.get("name", "World")
return f"Hello, {escape(name)} from Flask!"
app = FastAPI()
#app.get("/v2")
def read_main():
return {"message": "Hello World"}
app.mount("/v1", WSGIMiddleware(flask_app))
Update
While it is possible in the approach listed below, I genuinely think that we should avoid coupling different frameworks in such a monolith. Doing so could lead to unexpected bugs and make it harder to scale.
Instead, we could build 1 backend service in FastAPI, 1 Django Admin service for example, and then use NGINX to route traffic to these backend services. Using NGINX to route traffic to different backend services in production is common anyway.
Integration Of FastAPI With Django (WSGI)
https://github.com/jordaneremieff/django-fastapi-example.git
After hours of searching finally I found a great implementation in the link above. It worked seamlessly for me!
Testing
In order to make this simple to test, below are some few adjustments I made to the above reference:
api/models.py
class Item(models.Model):
title = models.CharField(max_length=50)
description = models.TextField()
# owner = models.ForeignKey(
# settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name="items"
# )
api/schemas.py
class Item(ItemBase):
# id: int
# owner_id: int
class Config:
orm_mode = True
POST
curl -d "{\"title\":\"le titre\", \"description\":\"la description\"}" -H "Content-Type: application/json" -X POST http://127.0.0.1:8000/api/items
GET
curl http://127.0.0.1:8000/api/items
Thank you for the awesome answers. Here is a little tweaked answer where I have fixed some imports as well as I have used a model from a Django app.
from fastapi import FastAPI
from fastapi.middleware.wsgi import WSGIMiddleware
from django.core.wsgi import get_wsgi_application
import os
from importlib.util import find_spec
from fastapi.staticfiles import StaticFiles
from django.conf import settings
# Export Django settings env variable
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
# Get Django WSGI app
django_app = get_wsgi_application()
# Import a model
# And always import your models after you export settings
# and you get Django WSGI app
from accounts.models import Account
# Create FasatAPI instance
app = FastAPI()
# Serve Django static files
app.mount('/static',
StaticFiles(
directory=os.path.normpath(
os.path.join(find_spec('django.contrib.admin').origin, '..', 'static')
)
),
name='static',
)
# Define a FastAPI route
#app.get('/fastapi-test')
def read_main():
return {
'total_accounts': Account.objects.count(),
'is_debug': settings.DEBUG
}
# Mount Django app
app.mount('/django-test', WSGIMiddleware(django_app))
Hint: I created a file named app.py in my Django project's root directory and it worked. Here is my directory structure:
.
├── accounts
│   ├── __init__.py
│   ├── admin.py
│   ├── apps.py
│   ├── migrations
│   │   ├── 0001_initial.py
│   │   ├── __init__.py
│   ├── models.py
│   ├── tests.py
│   └── views.py
├── app.py
├── db.sqlite3
├── project
│   ├── __init__.py
│   ├── asgi.py
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
└── manage.py
And run your FastAPI app:
(myvenv) ➜ project uvicorn --host 0.0.0.0 --port 8000 app:app --reload
INFO: Uvicorn running on http://0.0.0.0:8000 (Press CTRL+C to quit)
INFO: Started reloader process [48366] using statreload
INFO: Started server process [48368]
INFO: Waiting for application startup.
INFO: Application startup complete.
Hopefully, this will work for you. Now accessing /django-test will serve your Django project and /fastapi-test will serve the FastAPI part.
This configuration serves Django static files too and we can use our Django models in our FastAPI code as well. I'll test it further and I'll update this answer if I find any possibilities for improvement.
As Sumitrhan pointed out in a commet: There is also Django Ninja a Project that uses very similar concepts like Fast API (Routes, Pydandantic Model Validation) but simply is a Django App.
Given that current Django supports also async views in I see no point in mixing django and FastApi, to get the same feature set only much more complicated as not as good integrated.
there is good resource as follows:
Combine the power of FastAPI and Django

Structuring your Flask project the right way (no Blueprint)

Intro
I've read like a thousand posts on SO and other sites trying to figure out what's wrong with my Flask structure and why I can't seem to figure out something. As a last resort, I decided to finally ask the question here.
My project is really simple:
I have to fetch some data from some networking devices via API, process the data and store it in a Postgresql DB (most part of the code is in lib/).
This project is going to be deployed on multiple environments (test, dev, staging and prod).
To do the above I'm using the following:
Flask-SQLAlchemy + Flask-Migrate + Flask-Script - all of these for handling migrations and DB related operations;
Python-dotenv - for handling sensitive configuration data
Project details
My project structure looks like this:
my_project/
├── api/
├── app.py
├── config.py
├── __init__.py
├── lib/
│   ├── exceptions.py
│   └── f5_bigip.py
├── log.py
├── logs/
├── manage.py
├── migrations/
├── models/
│   ├── __init__.py
│   ├── model1.py
│   └── model2.py
└── run.py
My app.py looks like this:
import os
import sys
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
from dotenv import load_dotenv
from flask import Flask
from flask_migrate import Migrate
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
migrate = Migrate()
def create_app():
load_dotenv()
app = Flask(__name__)
environment = app.config['ENV']
if environment == 'production':
app.config.from_object('config.ProductionConfig')
elif environment == 'testing':
app.config.from_object('config.TestingConfig')
else:
app.config.from_object('config.DevelopmentConfig')
db.init_app(app)
migrate.init_app(app, db)
return app
My config.py looks like this:
import os
from sqlalchemy.engine.url import URL
PROJECT_ROOT = os.path.dirname(os.path.realpath(__file__))
class BaseConfig:
DEBUG = False
TESTING = False
DB_DRIVERNAME = os.getenv('DB_DRIVERNAME')
DB_HOST = os.getenv('DB_HOST')
DB_PORT = os.getenv('DB_PORT')
DB_NAME = os.getenv('DB_NAME')
DB_USERNAME = os.getenv('DB_USERNAME')
DB_PASSWORD = os.getenv('DB_PASSWORD')
DB = {
'drivername': DB_DRIVERNAME,
'host': DB_HOST,
'port': DB_PORT,
'database': DB_NAME,
'username': DB_USERNAME,
'password': DB_PASSWORD,
}
SQLALCHEMY_DATABASE_URI = URL(**DB)
SQLALCHEMY_TRACK_MODIFICATIONS = False
class DevelopmentConfig(BaseConfig):
DEVELOPMENT = True
DEBUG = True
class TestingConfig(BaseConfig):
TESTING = True
class StagingConfig(BaseConfig):
DEVELOPMENT = True
DEBUG = True
class ProductionConfig(BaseConfig):
pass
My __init__.py looks like this:
from contextlib import contextmanager
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker
# here, create_engine needs the SQLALCHEMY_DATABASE_URI
# how do I get it from the proper config?
engine = create_engine()
Session = sessionmaker(bind=engine)
#contextmanager
def session_scope():
"""
Provide a transactional scope around a series of operations.
"""
session = Session()
try:
yield session
session.commit()
except Exception as e:
print(f'Something went wrong here: {str(e)}. rolling back.')
session.rollback()
raise
finally:
session.close()
My manage.py looks like this:
from flask_script import Manager
from flask_migrate import MigrateCommand
from app import create_app
from models import *
manager = Manager(create_app)
manager.add_command('db', MigrateCommand)
if __name__ == '__main__':
manager.run()
My models/model1.py looks like this:
from sqlalchemy.dialects.postgresql import INET
from sqlalchemy.sql import func
from app import db
class Model1(db.Model):
__tablename__ = 'model1'
id = db.Column(db.BigInteger, primary_key=True, autoincrement=True)
ip_address = db.Column(INET, unique=True, nullable=False)
last_update = db.Column(db.DateTime(), server_default=func.now())
def __repr__(self):
return f'<Model1: {self.ip_address}>'
def __init__(self, ip_address):
self.ip_address = ip_address
Questions
Now, I have three main questions:
In my main __init__.py how can I import SQLALCHEMY_DATABASE_URI from the app's config?
Having the Session() object in the __init__.py doesn't seem too intuitive. Should it be placed in other places? For more context, the session is used in lib/f5_bigip.py and is probably going to be used in the api/ as well.
Is the overall project structure ok?
Your questions 1 and 2 are directly related to the part of your project that I found strange, so instead of answering those questions I'll just give you a much simpler and better way.
It seems in __init__.py you are implementing your own database sessions, just so that you can create a scoped session context manager. Maybe you've got that code from another project? It is not nicely integrated with the rest of your project, which uses the Flask-SQLAlchemy extension, you are just ignoring Flask-SQLAlchemy, which manages your database connections and sessions, and basically creating another connection into the database and new sessions.
What you should do instead is leverage the connections and sessions that Flask-SQLAlchemy provides. I would rewrite __init__.py as follows (doing this by memory, so excuse minor mistakes):
from contextlib import contextmanager
from app import db
#contextmanager
def session_scope():
"""
Provide a transactional scope around a series of operations.
"""
try:
yield db.session
session.commit()
except Exception as e:
print(f'Something went wrong here: {str(e)}. rolling back.')
db.session.rollback()
raise
finally:
db.session.close()
With this you are reusing the connection/sessions from Flask-SQLAlchemy. Your question 1 then is not a problem anymore. For question 2, you would use db.session anywhere in your app where you need database sessions.
Regarding question 3 I think you're mostly okay. I would suggest you do not use Flask-Script, which is a fairly old and unmaintained extension. Instead you can move your CLI to Flask's own CLI support.

Flask, managing DB connections(without ORM)

I'm newbie in Flask and web programming on the whole, so I'm trying to understand the principles of contexts and db operations of the framework.
Now I want to make out how to manage DB connections without Sql-Alchemy and other ORMs, just with plain sql.
So the simple example with sqlite3 db.
The structure of my test project:
.
├── application
│   ├── __init__.py
│   ├── routes.py
│   └── templates
│   ├── base.html
│   ├── index.html
├── config.py
├── requirements.txt
├── run.py
└── test.db
init.py
from flask import Flask,g
from config import Config
import sqlite3
app = Flask(__name__)
app.config.from_object(Config)
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect('test.db')
return db
#app.teardown_appcontext
def close_connection(exception):
db = getattr(g, '_database', None)
if db is not None:
db.close()
from application import routes
routes.py
# -*- coding: utf-8 -*-
from flask import render_template,redirect
from application import app, get_db
# import sqlite3
#app.route('/')
def index():
cur = get_db().cursor()
cur.execute('select*from users')
select=cur.fetchall()
return render_template('index.html',title='DBSelectTest', posts=select)
I've copied "get_db" and "close_connection" functions from the official site of Flask framework, but I'm not clearly understand how it works and what will be the difference if I use just simple code for "def get_db" without "g" like this:
con = sqlite3.connect("catalog.db")
cur = con.cursor()
And obviously close connections after query is done like this:
cur.close()
con.close()
I'm just trying to catch how the application and the request contexts work in that case with using g.
The main problem that I don't understand what is a "request" in that case.
My wrong understanding of this case:
So in init.py we create "global variable" g which is in application context and should be accessible for each tread in request context.
In routes.py we get query from client with root route("/") so in that moment request context is created and after that application context as well.
So as I understand "get_db" is accessible from our request context and we're able to connect to the db and use that g value in all functions inside the current tread? What about "close_connection"? Because of decorator "teardown_appcontext" the connections have to been closed after app context is failed or ended? Will it work in my code?
So, could anyone provide a correct case of using plain sql with separate connection function?
Flask application and request contexts behave like global variables for the purposes of your code, but are in fact proxies that will contain different values every time your application receives a new web request. The request context contains data specific to that particular web request such as form data, remote ip address, http headers, etc.
Every time a web request is received, new application and request contexts are created before your view function is called and these are then destroyed after a response has been returned and the processing of the web request has been completed. The g proxy is stored with the application context and it's used to store variables with a lifetime of that particular web request. This is used to pass information between functions called by flask as a result of events and signals.
In your code you use a decorator to register the function close_connection with the teardown_appcontext event, thus guaranteeing it is called after completion of handling of every web request. There are many other events that can be hooked to execute before or after your view function to provide pre- and post-processing of the request or response. The g proxy is merely used to store your database connection, which was created in your view function, and makes it available to the close_connection function where it is guaranteed to be closed. This prevents the database connection being left open if an error occurs in your application code.
The pattern, as shown below, is used to accomplish exactly the same thing as would be achieved by using a context manager (or try, except, finally block) to close the database connection within your function. This pattern is commonly used with an ORM to hide the underlying management of the database connection and reduce boilerplate code. The following code should produce the same effect without the use of events or the g proxy.
# -*- coding: utf-8 -*-
from flask import render_template, redirect
from application import app
from contextlib import closing
import sqlite3
def get_db():
return sqlite3.connect('test.db')
#app.route('/')
def index():
with closing(get_db()) as conn:
cur = conn.cursor()
cur.execute('select * from users')
select = cur.fetchall()
return render_template('index.html', title='DBSelectTest', posts=select)