How to paginate MongoEngine records in your Python 3 Flask application
Flask and MongoEngine help makes development work easier.
One common task in the development of backend applications is the pagination of database records. Without pagination, the application server can run out of memory while generating a response from the database records.
This post discusses a way to paginate MongoEngine records in your Python 3 Flask application using the facilities provided by the Flask-MongoEngine extension.
Installing flask-mongoengine to your Python 3 environment
pip install flask-mongoengine
Associating an instance of flask_mongoengine.MongoEngine with an instance of Flask
Once our Python 3 environment had included flask-mongoengine, we can proceed to associate an instance of flask_mongoengine.MongoEngine with an instance of Flask in our Python 3 script.
To do so, we can use either the following set of codes:
from flask import Flask
from flask_mongoengine import MongoEngine
app = Flask(__name__)
app.config.from_pyfile('the-config.cfg')
db = MongoEngine(app)
or the following set of codes:
from flask import Flask
from flask_mongoengine import MongoEngine
app = Flask(__name__)
app.config.from_pyfile('the-config.cfg')
db = MongoEngine()
# Init app later
db.init_app(app)
Defining a subclass of flask_mongoengine.Document to represent our MongoDB collection
The next set of codes that we need to write is the definition of a subclass of flask_mongoengine.Document that will represent our MongoDB collection:
# Note: the db variable refers to the flask_mongoengine.MongoEngine
# instance that we had created earlier.
class Friend(db.Document):
name = db.StringField(max_length=50, required=True)
phone_number = db.StringField(max_length=50, required=True)
Note that we had used the db variable that we can created earlier to get a reference to the flask_mongoengine.Document class. We had also defined the fields that we expect the documents in our MongoDB collection to have.
Calling the paginate function from flask_mongoengine.BaseQuerySet
Once we had defined a subclass of flask_mongoengine.Document, we can then use the following codes to query our MongoDB collection and get a paginated record of the result:
friends_pagination = Friend.objects.paginate(page=1, per_page=10) # Get information of current pagination session current_page = friends_pagination.page total_pages_for_query = friends_pagination.pages item_per_page = friends_pagination.per_page total_number_of_items_that_match_query = friends_pagination.total list_of_items = friends_pagination.items
We first define the page number and items per page via the page and per_page input parameters of the flask_mongoengine.BaseQuerySet.paginate function. The execution of this function will return an instance of flask_mongoengine.pagination.Pagination class that represents a particular page of a MongoDB query that we had indicated.
We can then use the instance of flask_mongoengine.pagination.Pagination to retrieve:
- the current page number via the
pageattribute. - the total number of pages for the MongoDB query via the
pagesattribute. - the number of items per page via the
per_pageattribute. - the total number of items that are returned for the MongoDB query via the
totalattribute. - the list of items in the current page via the
itemsattribute.
AttributeError: 'QuerySet' object has no attribute 'paginate'?
The paginate function is provided by the BaseQuerySet class inside the flask_mongoengine package which builds on the mongoengine package.
Therefore, there can be a chance where we accidentally define our MongoDB collection representation class with the Document class from the mongoengine package instead of the Document class from the flask_mongoengine package:
import mongoengine as db
class Friend(db.Document):
name = db.StringField(max_length=50, required=True)
phone_number = db.StringField(max_length=50, required=True)
Doing so will result in the call to Friend.objects to return an instance of mongoengine.QuerySet instead. This is why the AttributeError is thrown when we try to call the paginate function.