0

I have a question regarding the flask_track_usage module. All my blueprints should have the Trackusage function included. Unfortunately i didn't find a way to solve my problem. Why isn't it possible to simply use the flask.current_app?

route.py

import datetime
from uuid import uuid4
from flask import Blueprint, session, render_template, url_for, flash, redirect, current_app, request, jsonify
from flask_template.main.utils import my_func
import os
import json
from flask_track_usage import TrackUsage
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter


main = Blueprint('main', __name__)

t = TrackUsage(current_app, [
    PrintWriter(),
    OutputWriter(transform=lambda s: "OUTPUT: " + str(s))
])


@t.include
@main.before_request
def session_management():
    now = datetime.datetime.now()
    session_lifetime = current_app.config['SESSION_DURATION']

    # Create session, if not already existing
    if session.get('session_ID') is None:
        # Initiate session, set a random UUID as Session ID
        session['session_ID'] = str(uuid4())
        session.permanent = True  # will expire after 30 minutes of inactivity
        session['timeout'] = False
        print(f'Initated session with ID:', session.get('session_ID'))

        return redirect(url_for('main.index'))

    else:
        try:
            last_active = session.get('last_active')
            delta = now - last_active
            if delta.seconds > 1740:
                print(f'Note: Session lifetime less than one minute. Expires in:',
                              session_lifetime - delta.seconds, 'sec')
            if delta.seconds > session_lifetime:
                session['last_active'] = now
                session['timeout'] = True
                print(f'Your session has expired after 30 minutes, you have been logged out (files are deleted).')

                return redirect(url_for('main.logout'))

        except:
            pass

    try:
        session['last_active'] = now
    except:
        pass


@main.route('/')
def index():
    return redirect(url_for('main.home'))


@main.route('/home')
def home():
    return render_template('home.html', title='home', subheader='Template Main Page')

__init__.py

from flask import Flask
from flask_template.config import Config


def create_app(config_class=Config):

    app = Flask(__name__)
    app.config.from_object(Config)

    from flask_template.sample_extension.routes import sample_extension
    from flask_template.main.routes import main
    from flask_template.errors.handlers import errors

    app.register_blueprint(sample_extension)
    app.register_blueprint(main)
    app.register_blueprint(errors)

    return app

Config

import os
import json
from datetime import timedelta

with open(os.path.join(os.getcwd(), 'etc', 'app_config.json')) as config_file:
    config = json.load(config_file)


class Config:

    SECRET_KEY = config.get('SECRET_KEY')
    SESSION_DURATION = 1800  # 30 minutes for delete function
    PERMANENT_SESSION_LIFETIME = timedelta(minutes=30)  # session lifetime

    root_dir = os.path.join(os.path.realpath('.'), 'flask_template')

    # Path to template to illustrate download functionality
    TEMPLATE_FOLDER = os.path.join(root_dir, 'sample_extension', 'assets', 'template')
    TRACK_USAGE_USE_FREEGEOIP = False
    TRACK_USAGE_INCLUDE_OR_EXCLUDE_VIEWS = 'include'

run.py

from flask_template import create_app

from flask_track_usage import TrackUsage
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter

app = create_app()

if __name__ == '__main__':

    app.run(ssl_context=('******'),
            host='0.0.0.0',
            port=5000,
            debug=True)

error

RuntimeError: Working outside of application context.

Sergey Shubin
  • 3,040
  • 4
  • 24
  • 36
jonashe
  • 13
  • 3

1 Answers1

1

There are several global Flask variables such as current_app and g that can be accessed only while the application is running (more about them in the Flask Application Context documentation entry). Using them outside the application context raises RuntimeError.

You can instantiate TrackUsage without parameters in your routes.py module:

track_usage = TrackUsage()


@track_usage.include
@main.before_request
def session_management():
    ...

And then you can import it in your __init__.py module and apply to your application instance:

from flask import Flask
from flask_template.config import Config
from flask_track_usage.storage.printer import PrintWriter
from flask_track_usage.storage.output import OutputWriter


def create_app(config_class=Config):

    app = Flask(__name__)
    app.config.from_object(Config)

    from flask_template.sample_extension.routes import sample_extension, track_usage
    from flask_template.main.routes import main
    from flask_template.errors.handlers import errors

    track_usage.init_app(app, [
        PrintWriter(),
        OutputWriter(transform=lambda s: "OUTPUT: " + str(s)),
    ])

    app.register_blueprint(sample_extension)
    app.register_blueprint(main)
    app.register_blueprint(errors)

    return app

I have not found this solution in the Flask-Track-Usage documentation but it is a common interface for Flask extentions. It allows to instantiate an extension in one module and connect it to Flask application in main module.

Sergey Shubin
  • 3,040
  • 4
  • 24
  • 36