MongoDB for Flask Apps

Ryan Shea, Co-Founder of Halfmoon Labs

You're using Python + Flask, you say? Alright! Let's get you hooked up to a mongoDB database. While we're at it, let's make it simpler to manage your data by incorporating the MongoEngine ODM (an Object-Document Mapper, not to be confused with the equivalent for relational databases - an Object-Relational Mapper).

If you followed my first tutorial on Flask apps, you might have something like this in your app.py:

import os
from flask import Flask, render_template, send_from_directory

#----------------------------------------
# initialization
#----------------------------------------

app = Flask(__name__)

app.config.update(
    DEBUG = True,
)

#----------------------------------------
# controllers
#----------------------------------------

@app.route('/favicon.ico')
def favicon():
    return send_from_directory(os.path.join(app.root_path, 'static'), 'ico/favicon.ico')

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@app.route("/")
def index():
    return render_template('index.html')

#----------------------------------------
# launch
#----------------------------------------

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 5000))
    app.run(host='0.0.0.0', port=port)

Either way, it isn't that important. Just make sure you have a working Flask app before you continue.

create a mongodb database

Go to mongolab.com, sign up for a free account, and create a database. You'll need a username and password to connect to the database, so you can either use the pair you signed up with or create a new database user and use those credentials.

install mongoengine

Install mongoengine by issuing the following commands:

pip install mongoengine

pip install flask_mongoengine

pip freeze > requirements.txt

create secret key

python

>>> import os

>>> os.urandom(24)

you should get something like this: '{\xe9\t\x81W\xe4...' - copy and paste the output (sans quotes) into the quotes below, and place the entire line at the end of the initialization section

app.config["SECRET_KEY"] = ''

connect to your database

Now, add the code below to app.py in order to connect to the database. Fill in your database name, username, and password, as well as the host address, which you can find at the top of your database page.

#----------------------------------------
# database
#----------------------------------------

from mongoengine import connect
from flask.ext.mongoengine import MongoEngine

DB_NAME = 'crazydb'
DB_USERNAME = 'alex'
DB_PASSWORD = 'samplepassword'
DB_HOST_ADDRESS = 'ds000000.mongolab.com:00000/crazydb'

app.config["MONGODB_DB"] = DB_NAME
connect(DB_NAME, host='mongodb://' + DB_USERNAME + ':' + DB_PASSWORD + '@' + DB_HOST_ADDRESS)
db = MongoEngine(app)

Ok, try running "python app.py" to make sure this works.

Great! Now you can connect to your database and can start issuing queries.

query the database

Before you query the database, make sure you have models that define the objects for you to query. It'd be a good idea to put these in a separate file, like models.py. Here is an example:

import datetime

class User(db.DynamicDocument):
    created_at = db.DateTimeField(default=datetime.datetime.now, required=True)

    facebook_id = db.IntField(required=True, unique=True)
    name = db.StringField(max_length=255, required=True)

    def __unicode__(self):
        return self.name

    meta = {
        'indexes' : ['-created_at', 'facebook_id'],
        'ordering' : ['-created_at']
    }

Now that you have your model, you can define functions to query the db. Here is an example:

def get_user_from_db(facebook_id):
    if not facebook_id:
        raise ValueError()
    users_found = User.objects(facebook_id=facebook_id)
    if len(users_found) == 1:
        return users_found[0]
    elif len(users_found) == 0:
        return None
    else:
        raise Exception('Database Integrity Error')

In this case, User.objects will be empty at first. To make this interesting, you need to populate your database with data. Here is one way to do that:

user = get_user_from_db(facebook_id)
if user is None:
    user = User()
    user.facebook_id = facebook_id
    user.name = name
    user.save()

check the mongoengine documentation for more