Handling sessions and users

Exclusive offer: get 50% off this eBook here
Instant Flask Web Development [Instant]

Instant Flask Web Development [Instant] — Save 50%

Tap into Flask to build a complete application in a style that you control with this book and ebook

£8.99    £4.50
by Ron DuPlain | August 2013 | Open Source Web Development

This article by, Ron DuPlain, the author of Instant Flask Web Development, explains how to keep users logged in for on-going requests after authentication. Since HTTP is stateless, we need to track some data across requests with a session.

(For more resources related to this topic, see here.)

Getting ready

We will work from the app.py file from the sched directory and the models.py file.

How to do it...

  1. Flask provides a session object, which behaves like a Python dictionary, and persists automatically across requests. You can, in your Flask application code:

    from flask import session
    # ... in a request ...
    session['spam'] = 'eggs'
    # ... in another request ...
    spam = session.get('spam') # 'eggs'

  2. Flask-Login provides a simple means to track a user in Flask's session. Update requirements.txt:

    Flask
    Flask-Login
    Flask-Script
    Flask-SQLAlchemy
    WTForms

  3. Then:

    $ pip install -r requirements.txt

  4. We can then load Flask-Login into sched's request handling, in app.py:

    from flask.ext.login import LoginManager, current_user
    from flask.ext.login import login_user, logout_user
    from sched.models import User
    # Use Flask-Login to track current user in Flask's session.
    login_manager = LoginManager()
    login_manager.setup_app(app)
    login_manager.login_view = 'login'
    @login_manager.user_loader
    def load_user(user_id):
    """Flask-Login hook to load a User instance from ID."""
    return db.session.query(User).get(user_id)

  5. Flask-Login requires four methods on the User object, inside class User in models.py:

    def get_id(self):
    return str(self.id)
    def is_active(self):
    return True
    def is_anonymous(self):
    return False
    def is_authenticated(self):
    return True

    Flask-Login provides a UserMixin (flask.ext.login.UserMixin) if you prefer to use its default implementation.

  6. We then provide routes to log the user in when authenticated and log out. In app.py:

    @app.route('/login/', methods=['GET', 'POST']) def login(): if current_user.is_authenticated(): return redirect(url_for('appointment_list')) form = LoginForm(request.form) error = None if request.method == 'POST' and form.validate(): email = form.username.data.lower().strip() password = form.password.data.lower().strip() user, authenticated = \ User.authenticate(db.session.query, email, password) if authenticated: login_user(user) return redirect(url_for('appointment_list')) else: error = 'Incorrect username or password.' return render_template('user/login.html', form=form, error=error) @app.route('/logout/') def logout(): logout_user() return redirect(url_for('login'))

  7. We then decorate every view function that requires a valid user, in app.py:

    from flask.ext.login import login_required
    @app.route('/appointments/')
    @login_required
    def appointment_list():
    # ...

How it works...

On login_user, Flask-Login gets the user object's ID from User.get_id and stores it in Flask's session. Flask-Login then sets a before_request handler to load the user instance into the current_user object, using the load_user hook we provide. The logout_user function then removes the relevant bits from the session.

If no user is logged in, then current_user will provide an anonymous user object which results in current_user.is_anonymous() returning True and current_user. is_authenticated() returning False, which allows application and template code to base logic on whether the user is valid. (Flask-Login puts current_user into all template contexts.) You can use User.is_active to make user accounts invalid without actually deleting them, by returning False as appropriate.

View functions decorated with login_required will redirect the user to the login view if the current user is not authenticated, without calling the decorated function.

There's more...

Flask's session supports display of messages and protection against request forgery.

Flashing messages

When you want to display a simple message to indicate a successful operation or a failure quickly, you can use Flask's flash messaging, which loads the message into the session until it is retrieved. In application code, inside request handling code:

from flask import flash
flash('Sucessfully did that thing.', 'success')

In template code, where you can use the 'success' category for conditional display:

{% for cat, m in get_flashed_messages(with_categories=true) %}
<div class="alert">{{ m }}</div>
{% endfor %}

Cross-site request forgery protection

Malicious web code will attempt to forge data-altering requests for other web services. To protect against forgery, you can load a randomized token into the session and into the HTML form, and reject the request when the two do not match. This is provided in the Flask-SeaSurf extension, pythonhosted.org/Flask-SeaSurf/ or the Flask-WTF extension (which integrates WTForms), pythonhosted.org/Flask-ETF/.

Summary

This article explained how to keep users logged in for on-going requests after authentication. It shed light on how Flask provides a session object, which behaves like a Python dictionary, and persists automatically across requests. It also spoke about coding in Flask application. We got acquainted with flashing messages and cross-site request forgery protection.

Resources for Article:


Further resources on this subject:


Instant Flask Web Development [Instant] Tap into Flask to build a complete application in a style that you control with this book and ebook
Published: August 2013
eBook Price: £8.99
See more
Select your format and quantity:

About the Author :


Ron DuPlain

Ron DuPlain is a core contributor to the Flask project, and has built dozens of production applications with Flask. He has been thinking in Python since 2005, applying it to a variety of applications from embedded systems to web development. He is based in Charlottesville, Virginia, USA, where he runs the local Python meetup group and is an organizer of the local bar camp unconferences. He holds a Bachelors in Science in Computer engineering from the University of Cincinnati and a Masters in Systems engineering from the University of Virginia.

Books From Packt


Learning IPython for Interactive Computing and Data Visualization
Learning IPython for Interactive Computing and Data Visualization

Python Geospatial Development - Second Edition
Python Geospatial Development - Second Edition

Programming ArcGIS 10.1 with Python Cookbook
Programming ArcGIS 10.1 with Python Cookbook

Python 2.6 Text Processing: Beginners Guide
Python 2.6 Text Processing: Beginners Guide

Python Testing Cookbook
Python Testing Cookbook

Expert Python Programming
Expert Python Programming

Matplotlib for Python Developers
Matplotlib for Python Developers

 Python 3 Object Oriented Programming
Python 3 Object Oriented Programming


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software