Flask-Paginate with CouchDB

629 Views Asked by At

I found here a nice template for a pagination. However, this example was done with SQLlite, but I rewrote in order to be able to use CouchDB.

This script creates users and save them to CouchDB:

from couchdb import Server
import sys

def fill_data(users_no):
      for i in range(users_no):
          doc = {
                  '_id': str(i),
                  'uname': "name_" + str(i),
                }
          db.save(doc)


if __name__ == '__main__':
    server = Server()
    db = server.create("pagination")

    fill_data(1000)

I modified the orginal app.py script in onrder to be able to use CouchDB. This is the modified script:

from __future__ import unicode_literals
from flask import Flask, render_template, g, current_app, request
from flask.ext.paginate import Pagination
from couchdb import Server

app = Flask(__name__)
app.config.from_pyfile('app.cfg')

@app.route('/')
def index():
    """
    Map function
    function(doc) {
      emit(doc._id, doc.uname);
    }
    """
    for row in db.view('_design/snp/_view/by_unames'):
        print row

    total = ???
    print total
    page, per_page, offset = get_page_items()
    pagination = get_pagination(page=page,
                per_page=per_page,
                total=total,
                record_name=users,
                )
    return render_template('index.html', users=users,
              page=page,
              per_page=per_page,
              pagination=pagination,
              )


def get_css_framework():
    return current_app.config.get('CSS_FRAMEWORK', 'bootstrap3')


def get_link_size():
    return current_app.config.get('LINK_SIZE', 'sm')


def show_single_page_or_not():
    return current_app.config.get('SHOW_SINGLE_PAGE', False)


def get_page_items():
    page = int(request.args.get('page', 1))
    per_page = request.args.get('per_page')
    if not per_page:
            per_page = current_app.config.get('PER_PAGE', 10)
    else:
            per_page = int(per_page)

    offset = (page - 1) * per_page
    return page, per_page, offset


def get_pagination(**kwargs):
      kwargs.setdefault('record_name', 'records')
      return Pagination(css_framework=get_css_framework(),
          link_size=get_link_size(),
          show_single_page=show_single_page_or_not(),
          **kwargs
          )

if __name__ == '__main__':

    server = Server()
    db = server["pagination"]
    app.run(debug=True)
  • What is the best way to get the total count from the view?

  • Is there a way to avoid to recalculate total count by clicking to the next or previous page in the pagination menu?

1

There are 1 best solutions below

0
On BEST ANSWER

CouchDB makes this easy because it calculates the total numbers of docs in a view automatically.

Let's take a look at an example, and throw in some query parameters while we are at it:

curl http://127.0.0.1:5984/pagination/_design/pagination/_view/by_unames?limit=11&startkey=%22101%22

This yields

{"total_rows":1000,"offset":4,"rows":[
{"id":"101","key":"101","value":"name_101"},
{"id":"102","key":"102","value":"name_102"},
{"id":"103","key":"103","value":"name_103"},
{"id":"104","key":"104","value":"name_104"},
{"id":"105","key":"105","value":"name_105"},
{"id":"106","key":"106","value":"name_106"},
{"id":"107","key":"107","value":"name_107"},
{"id":"108","key":"108","value":"name_108"},
{"id":"109","key":"109","value":"name_109"},
{"id":"11","key":"11","value":"name_11"},
{"id":"110","key":"110","value":"name_110"}
]}

Notice that although the limit query parameter was used to only get 11 documents, total_rows still is 1000, which is the total count of docs in the view.

Also note that the startkey parameter can be used to tell couchDB which document to start counting at. This can be used to create a fast, "linked-list" style pagination, which is the method recommended in the CouchDB guide.

For your case specifically, where you are using the python-couchdb library, a line such as

 x = db.view('pagination/by_unames', limit=11, startkey="101")

can be used. Then x.rows will have 11 rows, starting with the document with id of "101", and x.total_rows will be 1000, which is the total count of docs in the view.