1. Tutorial¶
This tutorial introduces MongoEngine by means of example — we will walk through how to create a simple Tumblelog application. A tumblelog is a blog that supports mixed media content, including text, images, links, video, audio, etc. For simplicity’s sake, we’ll stick to text, image, and link entries. As the purpose of this tutorial is to introduce MongoEngine, we’ll focus on the data-modelling side of the application, leaving out a user interface.
1.1. Getting started¶
Before we start, make sure that a copy of MongoDB is running in an accessible location — running it locally will be easier, but if that is not an option then it may be run on a remote server. If you haven’t installed MongoEngine, simply use pip to install it like so:
$ python -m pip install mongoengine
Before we can start using MongoEngine, we need to tell it how to connect to our
instance of mongod. For this we use the connect()
function. If running locally, the only argument we need to provide is the name
of the MongoDB database to use:
from mongoengine import *
connect('tumblelog')
There are lots of options for connecting to MongoDB, for more information about them see the Connecting to MongoDB guide.
1.2. Defining our documents¶
MongoDB is schemaless, which means that no schema is enforced by the database — we may add and remove fields however we want and MongoDB won’t complain. This makes life a lot easier in many regards, especially when there is a change to the data model. However, defining schemas for our documents can help to iron out bugs involving incorrect types or missing fields, and also allow us to define utility methods on our documents in the same way that traditional ORMs do.
In our Tumblelog application we need to store several different types of information. We will need to have a collection of users, so that we may link posts to an individual. We also need to store our different types of posts (eg: text, image and link) in the database. To aid navigation of our Tumblelog, posts may have tags associated with them, so that the list of posts shown to the user may be limited to posts that have been assigned a specific tag. Finally, it would be nice if comments could be added to posts. We’ll start with users, as the other document models are slightly more involved.
1.2.1. Users¶
Just as if we were using a relational database with an ORM, we need to define
which fields a User
may have, and what types of data they might store:
class User(Document):
email = StringField(required=True)
first_name = StringField(max_length=50)
last_name = StringField(max_length=50)
This looks similar to how the structure of a table would be defined in a regular ORM. The key difference is that this schema will never be passed on to MongoDB — this will only be enforced at the application level, making future changes easy to manage. Also, the User documents will be stored in a MongoDB collection rather than a table.
1.2.2.3. Comments¶
A comment is typically associated with one post. In a relational database, to display a post with its comments, we would have to retrieve the post from the database and then query the database again for the comments associated with the post. This works, but there is no real reason to be storing the comments separately from their associated posts, other than to work around the relational model. Using MongoDB we can store the comments as a list of embedded documents directly on a post document. An embedded document should be treated no differently than a regular document; it just doesn’t have its own collection in the database. Using MongoEngine, we can define the structure of embedded documents, along with utility methods, in exactly the same way we do with regular documents:
We can then store a list of comment documents in our post document: