How can I set the current session as 'logged in' using Python in Flask with Flask-SQLAlchemy?


Question

I am trying to learn how to build a basic Flask application with Python. I first followed their excellent tutorial to make a simple blog. The tutorial has you import session from flask. This is later set to "logged in," and only when it is such can the user write posts. For instance, the login function is as follows:

@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        if request.form['username'] != app.config['USERNAME']:
            error = 'Invalid username'
        elif request.form['password'] != app.config['PASSWORD']:
            error = 'Invalid password'
        else:
            session['logged_in'] = True
            flash('You were logged in')
            return redirect(url_for('show_entries'))
    return render_template('login.html', error=error)

and then later, another function checks to see whether or not the session is indeed on 'logged_in':

@app.route('/add', methods=['GET', 'POST'])
def add_entry():
    if not session.get('logged_in'):
        abort(401)
    g.db.execute('insert into entries (title, text) values (?, ?)',
                 [request.form['title'], request.form['text']])
    g.db.commit()
    flash('New entry was successfully posted')
    return redirect(url_for('show_entries'))

When I try to do this in my application, though, I get 500 Internal Server Error:

Internal Server Error

The server encountered an internal error and was unable to complete your request. Either the server is overloaded or there is an error in the application.

I think this is because in the tutorial, an sqlite database is used, whereas I am using Flask-SQLAlchemy when I get the error. Could this be the source of the problem, and if so, is there a recommended way to do similar? That is, allow the application to check to see if someone is logged in?

Below is my code in its entirety:

from flask import Flask, request, session, redirect, url_for, render_template
from flask.ext.sqlalchemy import SQLAlchemy



app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/z.db'
DEBUG = True
db = SQLAlchemy(app)

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True)
    email = db.Column(db.String(120), unique=True)
    password = db.Column(db.String(160), unique=True)

    def __init__(self, username, email, password):
        self.username = username
        self.email = email
        self.password = password

    def __repr__(self):
        return '<User %r>' % self.username

@app.route('/', methods=['GET', 'POST'])
def home():
    #check to see if logged in
    if session['logged_in'] == True:
        note = "this text is displayed because you are logged in."              
    note=None
    if request.method == 'POST':
        new_user = User(request.form['username'], request.form['email'], request.form['password'])
        #before making the new user, check to make sure the entered information isn't already in the db
        if User.query.filter_by(username=request.form['username']).first() != None:
            note = "sorry, this username has already been taken"
        elif User.query.filter_by(email=request.form['email']).first() != None :
            note = "sorry, this email address is already associated with an account."   
        else:   
            db.session.add(new_user)
            db.session.commit()
            session['logged_in'] = True
            redirect(url_for('home'))
    return render_template('index.html', note=note)

@app.route('/login', methods=['GET', 'POST'])
def signin():
    note=None
    if request.method == 'POST':
        #get username and search for it in db
        tag = request.form['username']
        #if the entry contains '@', search db as email address
        if tag.find('@') != -1:
            user = User.query.filter_by(email=tag).first()
        else:
            user = User.query.filter_by(username=tag).first()   
        #if user exists, get password associated with it
        if user != None:
            password = user.password

            #see if db email equals email input in HTML
            if password == request.form['password']:
                session['logged_in'] = True
                return redirect(url_for('home'))
            else:
                note='wrong password'   
        else:
            #call an error message
            note='this username does not seem to exist. that is all i know'
    return render_template('login.html', note=note)         

if __name__ == '__main__':
    app.run()        

Many thanks in advance.

1
1
11/10/2012 10:52:49 PM

Accepted Answer

You need to set app.secret_key to be able to use sessions:

In addition to the request object there is also a second object called session which allows you to store information specific to a user from one request to the next. This is implemented on top of cookies for you and signs the cookies cryptographically. What this means is that the user could look at the contents of your cookie but not modify it, unless they know the secret key used for signing.

In order to use sessions you have to set a secret key. Here is how sessions work

2
11/10/2012 11:06:46 PM

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon