Reputation: 1325
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
Upvotes: 5
Views: 8988
Reputation: 2273
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
Upvotes: 12