{"id":517,"date":"2018-04-20T20:07:02","date_gmt":"2018-04-20T12:07:02","guid":{"rendered":"https:\/\/www.techcoil.com\/blog\/?p=517"},"modified":"2018-04-20T14:37:31","modified_gmt":"2018-04-20T06:37:31","slug":"how-to-paginate-mongoengine-records-in-your-python-3-flask-application","status":"publish","type":"post","link":"https:\/\/www.techcoil.com\/blog\/how-to-paginate-mongoengine-records-in-your-python-3-flask-application\/","title":{"rendered":"How to paginate MongoEngine records in your Python 3 Flask application"},"content":{"rendered":"<p><a href=\"http:\/\/flask.pocoo.org\/\" rel=\"noopener\" target=\"_blank\">Flask<\/a> and <a href=\"http:\/\/mongoengine.org\/\" rel=\"noopener\" target=\"_blank\">MongoEngine<\/a> help makes development work easier. <\/p>\n<p>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.<\/p>\n<p>This post discusses a way to paginate MongoEngine records in your Python 3 Flask application using the facilities provided by the <a href=\"http:\/\/docs.mongoengine.org\/projects\/flask-mongoengine\" rel=\"noopener\" target=\"_blank\">Flask-MongoEngine<\/a> extension.<\/p>\n<h2>Installing flask-mongoengine to your Python 3 environment<\/h2>\n<pre class=\"brush: bash; title: ; notranslate\" title=\"\">\r\npip install flask-mongoengine\r\n<\/pre>\n<h2>Associating an instance of <code>flask_mongoengine.MongoEngine<\/code> with an instance of <code>Flask<\/code><\/h2>\n<p>Once our Python 3 environment had included flask-mongoengine, we can proceed to associate an instance of <code>flask_mongoengine.MongoEngine<\/code> with an instance of <code>Flask<\/code> in our Python 3 script.<\/p>\n<p>To do so, we can use either the following set of codes:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nfrom flask import Flask\r\nfrom flask_mongoengine import MongoEngine\r\n\r\napp = Flask(__name__)\r\napp.config.from_pyfile('the-config.cfg')\r\ndb = MongoEngine(app)\r\n<\/pre>\n<p>or the following set of codes:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nfrom flask import Flask\r\nfrom flask_mongoengine import MongoEngine\r\n\r\napp = Flask(__name__)\r\napp.config.from_pyfile('the-config.cfg')\r\ndb = MongoEngine()\r\n# Init app later\r\ndb.init_app(app)\r\n<\/pre>\n<h2>Defining a subclass of <code>flask_mongoengine.Document<\/code> to represent our MongoDB collection<\/h2>\n<p>The next set of codes that we need to write is the definition of a subclass of <code>flask_mongoengine.Document<\/code> that will represent our MongoDB collection:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n# Note: the db variable refers to the flask_mongoengine.MongoEngine \r\n# instance that we had created earlier.\r\nclass Friend(db.Document):\r\n    \r\n    name = db.StringField(max_length=50, required=True)\r\n    phone_number = db.StringField(max_length=50, required=True)\r\n    \r\n<\/pre>\n<p>Note that we had used the <code>db<\/code> variable that we can created earlier to get a reference to the <code>flask_mongoengine.Document<\/code> class. We had also defined the fields that we expect the documents in our MongoDB collection to have.<\/p>\n<h2>Calling the paginate function from <code>flask_mongoengine.BaseQuerySet<\/code><\/h2>\n<p>Once we had defined a subclass of <code>flask_mongoengine.Document<\/code>, we can then use the following codes to query our MongoDB collection and get a paginated record of the result:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nfriends_pagination = Friend.objects.paginate(page=1, per_page=10)\r\n# Get information of current pagination session\r\ncurrent_page = friends_pagination.page\r\ntotal_pages_for_query = friends_pagination.pages\r\nitem_per_page = friends_pagination.per_page\r\ntotal_number_of_items_that_match_query = friends_pagination.total\r\nlist_of_items = friends_pagination.items\r\n<\/pre>\n<p>We first define the page number and items per page via the <code>page<\/code> and <code>per_page<\/code> input parameters of the <code>flask_mongoengine.BaseQuerySet.paginate<\/code> function. The execution of this function will return an instance of <code>flask_mongoengine.pagination.Pagination<\/code> class that represents a particular page of a MongoDB query that we had indicated.<\/p>\n<p>We can then use the instance of <code>flask_mongoengine.pagination.Pagination<\/code> to retrieve:<\/p>\n<ul>\n<li>the current page number via the <code>page<\/code> attribute.<\/li>\n<li>the total number of pages for the MongoDB query via the <code>pages<\/code> attribute.<\/li>\n<li>the number of items per page via the <code>per_page<\/code> attribute.<\/li>\n<li>the total number of items that are returned for the MongoDB query via the <code>total<\/code> attribute.<\/li>\n<li>the list of items in the current page via the <code>items<\/code> attribute.<\/li>\n<\/ul>\n<h2>AttributeError: 'QuerySet' object has no attribute 'paginate'?<\/h2>\n<p>The <code>paginate<\/code> function is provided by the <code>BaseQuerySet<\/code> class inside the <code>flask_mongoengine<\/code> package which builds on the <code>mongoengine<\/code> package. <\/p>\n<p>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 <code>Document<\/code> class from the <code>flask_mongoengine<\/code> package:<\/p>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\n\r\nimport mongoengine as db\r\nclass Friend(db.Document):\r\n    \r\n    name = db.StringField(max_length=50, required=True)\r\n    phone_number = db.StringField(max_length=50, required=True)\r\n    \r\n\r\n<\/pre>\n<p>Doing so will result in the call to <code>Friend.objects<\/code> to return an instance of <code>mongoengine.QuerySet<\/code> instead. This is why the <a href=\"https:\/\/docs.python.org\/3\/library\/exceptions.html#AttributeError\" rel=\"noopener\" target=\"_blank\"><code>AttributeError<\/code><\/a> is thrown when we try to call the <code>paginate<\/code> function.<\/p>\n\n      <ul id=\"social-sharing-buttons-list\">\n        <li class=\"facebook\">\n          <a href=\"https:\/\/www.facebook.com\/sharer\/sharer.php?u=https%3A%2F%2Fwp.me%2Fp245TQ-8l\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n            <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Facebook.png\" alt=\"Facebook icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"twitter\">\n          <a href=\"https:\/\/twitter.com\/intent\/tweet?text=&url=https%3A%2F%2Fwp.me%2Fp245TQ-8l&via=Techcoil_com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Twitter.png\" alt=\"Twitter icon\"> Tweet\n          <\/a>\n        <\/li>\n        <li class=\"linkedin\">\n          <a href=\"https:\/\/www.linkedin.com\/shareArticle?mini=1&title=&url=https%3A%2F%2Fwp.me%2Fp245TQ-8l&source=https:\/\/www.techcoil.com\" target=\"_blank\" role=\"button\" rel=\"nofollow\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/linkedin.png\" alt=\"Linkedin icon\"> Share\n          <\/a>\n        <\/li>\n        <li class=\"pinterest\">\n          <a href=\"https:\/\/pinterest.com\/pin\/create\/button\/?url=https%3A%2F%2Fwww.techcoil.com%2Fblog%2Fwp-json%2Fwp%2Fv2%2Fposts%2F517&description=\" class=\"pin-it-button\" target=\"_blank\" role=\"button\" rel=\"nofollow\" count-layout=\"horizontal\">\n          <img decoding=\"async\" src=\"\/ph\/img\/3rd-party\/social-icons\/Pinterest.png\" alt=\"Pinterest icon\"> Save\n          <\/a>\n        <\/li>\n      <\/ul>\n    ","protected":false},"excerpt":{"rendered":"<p><a href=\"http:\/\/flask.pocoo.org\/\" rel=\"noopener\" target=\"_blank\">Flask<\/a> and <a href=\"http:\/\/mongoengine.org\/\" rel=\"noopener\" target=\"_blank\">MongoEngine<\/a> help makes development work easier. <\/p>\n<p>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.<\/p>\n<p>This post discusses a way to paginate MongoEngine records in your Python 3 Flask application using the facilities provided by the <a href=\"http:\/\/docs.mongoengine.org\/projects\/flask-mongoengine\" rel=\"noopener\" target=\"_blank\">Flask-MongoEngine<\/a> extension.<\/p>\n","protected":false},"author":1,"featured_media":950,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"footnotes":""},"categories":[375],"tags":[480,152,481,521,226,233,254],"jetpack_featured_media_url":"https:\/\/www.techcoil.com\/blog\/wp-content\/uploads\/mongodb-logo.jpg","jetpack_shortlink":"https:\/\/wp.me\/p245TQ-8l","jetpack-related-posts":[],"jetpack_likes_enabled":true,"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/517"}],"collection":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/comments?post=517"}],"version-history":[{"count":0,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/posts\/517\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media\/950"}],"wp:attachment":[{"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/media?parent=517"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/categories?post=517"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.techcoil.com\/blog\/wp-json\/wp\/v2\/tags?post=517"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}