Bottle.py session with Beaker
beaker, bottle, python
Solution
Using `beaker` in your `bottle` application is easy. First, set up your Bottle app:
import bottle
from bottle import request, route, hook
import beaker.middleware
session_opts = {
'session.type': 'file',
'session.data_dir': './session/',
'session.auto': True,
}
app = beaker.middleware.SessionMiddleware(bottle.app(), session_opts)
And later on:
bottle.run(app=app)
With this in place, every time you receive a request, your Beaker session will be available as `request.environ['beaker_session']`. I usually do something like this for convenience:
@hook('before_request')
def setup_request():
request.session = request.environ['beaker.session']
This arranges to run `setup_request` before handling any request; we're using the `bottle.request` variable (see the earlier import statement), which is a thread-local variable with information about the current request. From this point on, I can just refer to `request.session` whenever I need it, e.g.:
@route('/')
def index():
if 'something' in request.session:
return 'It worked!'
request.session['something'] = 1
Problem
first time questioner here. I'm currently struggling on how to use Beaker properly using the Bottle micro-framework. Here's the problematic program: ``` #!/usr/bin/python # -*- coding: utf-8 -*- # filename: server.py import bottle as app from beaker.middleware import SessionMiddleware session_options = { 'session.type': 'file', 'session.data_dir': './session/', 'session.auto': True, } app_middlware = SessionMiddleware(app.app(), session_options) app_session = app.request.environ.get('beaker.session') @app.route('/login') def login(): app_session = app.request.environ.get('beaker.session') app_session['logged_in'] = True @app.route('/logout') def logout(): app_session = app.request.environ.get('beaker.session') if app_session.get('logged_in'): app_session['logged_in'] = False return 'You are logged out' app.redirect('/login') @app.route('/dashboard') def dashboard(): app_session = app.request.environ.get('beaker.session') if app_session.get('logged_in'): return 'You are logged in' app.redirect('/login') app.debug(True) app.run(app=app_middlware, reloader=True) ``` If you noticed, I keep on calling `app_session = app.request.environ.get('beaker.session')` on every `def` block so just it will not return an error like: `TypeError: 'NoneType' object does not support item assignment` --- it seems that Python doesn't recognize variables that is outside its function (correct me if I'm wrong). And here are the questions: - What should I do to only have one instance of `app_session = app.request.environ.get('beaker.session')` so it can be available to every `def` blocks (I really need one instance since it's the same session to be checked and used). - If this is the only way (it's ugly though), then should I just combine all routes that requires a session just so I can achieve the single instance of `app_session`? Something like: ``` @app.route('/<path:re:(login|dashboard|logout)\/?>') def url(path): app_session = app.request.environ.get('beaker.session') if 'login' in path: app_session['logged_in'] = True elif 'logout' in path: if app_session.get('logged_in'): # app_session.delete() it doesn't seem to work? app_session['logged_in'] = False return 'You are logged out' app.redirect('/login') elif 'dashboard' in path: if app_session.get('logged_in'): return 'You are logged in' app.redirect('/login') ```