Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to execute a block of code only once in flask?

Tags:

python

flask

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
like image 461
ramu Avatar asked Jul 07 '15 04:07

ramu


People also ask

Does Flask run single thread?

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.

How do I run a Flask in a separate thread?

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.

Does Flask use multiple processes?

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.


Video Answer


1 Answers

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
like image 55
Boris Avatar answered Oct 22 '22 15:10

Boris