I want to log, who is logging in the app that uses FLASK.
I tried using
@app.before_request
but the problem is I need to access the username which is through flask globals and I get none if I use this decorator.
Also, using global variables like below also doesn`t work. How do I get a global variable in request context?
import logging
import time
from flask import request, flash
from flask import g
from forms import QueryForm, RequestForm, Approve_Reject_Btn_Form
from query.sqlQuery import SQLQuery
from database.oracle import Database
import datetime
from requests import Session
logger = logging.getLogger(__name__)
login_count = 0
'''
Homepage route - Displays all the tables in the homepage
'''
@app.route('/')
@app.route('/index')
def index():
try:
if not g.identity.is_authenticated():
return render_template('homepage.html')
else:
try:
global login_count
if login_count == 0:
username = g.identity.name
user_ip = request.headers.get('IP_header')
current_time = time.strftime('%c')
db = Database(db_config.username, db_config.password)
query = "INSERT INTO UserIP (username, login_time, ip_address) values ('%s', systimestamp, '%s')" % (username, user_ip)
dml_query(query)
logger.debug('User : %s, ip : %s, noted at time : %s, login_count : %s', username , user_ip, current_time, login_count)
login_count = 1
Using the simple app. run() from within Flask creates a single synchronous server on a single thread capable of serving only one client at a time. It is intended for use in controlled environments with low demand (i.e. development, debugging) for exactly this reason.
To start a Python Flask application in separate thread, we set the use_reloader to False when we call app. run . And then we create a Thread instance with the Flask app by setting the function that calls app. run as the value of the target argument.
Modern web servers like Flask, Django, and Tornado are all able to handle multiple requests simultaneously. The concept of multitasking is actually very vague due to its various interpretations. You can perform multitasking using multiprocessing, multithreading, or asyncio.
As far as your question "How to execute a block of code only once in flask?" goes, something like this should work fine:
app = Flask(__name__)
@app.before_first_request
def do_something_only_once():
app.logger.setLevel(logging.INFO)
app.logger.info("Initialized Flask logger handler")
The second part of your question is how to setup global variable, like the login counter in your example. For something like this I would recommend that you use an external cache. See example below with the werkzeug SimpleCache class. In production you should replace SimpleCache with redis or mongodb.
from werkzeug.contrib.cache import SimpleCache
class Cache(object):
cache = SimpleCache(threshold = 1000, default_timeout = 3600)
@classmethod
def get(cls, key = None):
return cls.cache.get(key)
@classmethod
def delete(cls, key = None):
return cls.cache.delete(key)
@classmethod
def set(cls, key = None, value = None, timeout = 0):
if timeout:
return cls.cache.set(key, value, timeout = timeout)
else:
return cls.cache.set(key, value)
@classmethod
def clear(cls):
return cls.cache.clear()
You can use Cache class like this.
from mycache import Cache
@app.route('/')
@app.route('/index')
def index():
if not g.identity.is_authenticated():
return render_template('homepage.html')
else:
login_count = Cache.get("login_count")
if login_count == 0:
# ...
# Your code
login_count += 1
Cache.set("login_count", login_count)
EDIT 1: Added after_request example
Per Flask documentation, after_request decorator is used to run registered function after each request. It can be used to invalidate cache, alter response object, or pretty much anything that would require a specific response modification.
@app.after_request
def after_request_callback(response):
# Do something with the response (invalidate cache, alter response object, etc)
return response
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With