Working with Pagination

Creating fixtures

When your address book will be full of entry, you will need to add a pagination on your API. As it is a common need, REST API Framework implement a very easy way of doing so.

Before you can play with the pagination process, you will need to create more data. You can create those records the way you want:

  • direct insert into the database
sqlite3 adress_book.db
INSERT INTO users VALUES ("Nick", "Furry", 6);
  • using the datastore directly
store = SQLiteDataStore({"name": "adress_book.db", "table": "users"}, UserModel)
store.create({"first_name": "Nick", "last_name": "Furry"})
  • using your API
curl -i -H "Content-type: application/json" -X POST -d '{"first_name": "Nick", "last_name": "Furry"}'  http://localhost:5000/users/

each on of those methods have advantages and disavantages but they all make the work done. For this example, I propose to use the well know requests package with a script to create a bunch of random records:

For this to work you need to install resquests : http://docs.python-requests.org/en/latest/user/install/#install

import json
import requests
import random
import string

def get_random():
    return ''.join(
                   random.choice(
                     string.ascii_letters) for x in range(
                     int(random.random() * 20)
                     )
                   )

for i in range(200):
    requests.post("http://localhost:5000/users/", data=json.dumps({"first_name": get_random(), "last_name": get_random()}))

Browsering Through Paginated objects

Of course you get 20 records but the most usefull part is the meta key:

{"meta":
    {"count": 20,
    "total_count": 802,
    "next": "?offset=20",
    "filters": {},
    "offset": 0,
    "previous": "null"}
}

You can use the “next” key to retreive the 20 next rows:

curl -i "http://localhost:5000/users/?offset=20"
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 1849
Server: Werkzeug/0.8.3 Python/2.7.2
Date: Tue, 15 Oct 2013 11:38:59 GMT
{"meta": {"count": 20, "total_count": 802, "next": "?offset=40",
"filters": {}, "offset": 20, "previous": "?offset=0"}, "object_list":
[<snip for readability>]}

Note

The count and offset keywords can be easily changed to match your needs. pagination class may take an offset_key and count_key parameters. So if you prefer to use first_id and limit, you can change your Paginator class to do so:

"options": {"pagination": Pagination(20,
                                 offset_key="first_id",
                                 count_key="limit")

Wich will results in the following:

curl -i "http://localhost:5000/users/"
{"meta": {"first_id": 0, "total_count": 802, "next": "?first_id=20",
"limit": 20, "filters": {}, "previous": "null"}, "object_list": [<snip
for readability>]

Pagination and Filters

Pagination and filtering play nice together

curl -i "http://localhost:5000/users/?last_name=America"
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 298
Server: Werkzeug/0.8.3 Python/2.7.2
Date: Tue, 15 Oct 2013 12:14:59 GMT

{"meta": {"count": 20,
          "total_count": 2,
          "next": "null",
          "filters": {"last_name": "America"},
          "offset": 0,
          "previous": "null"},
          "object_list": [
              {"first_name": "Joe",
               "last_name": "America",
               "ressource_uri": "/users/1/"},
              {"first_name": "Bob",
               "last_name": "America",
               "ressource_uri": "/users/3/"}
          ]
 }

Next: Loading multiple endpoint