Back to Examples Run Example

examples/rest.py

import uuid
import json
from py4web.core import action, request, response, Fixture
from .models import db, Field


# for demo purposes we create a table of tokens
# in practice you want to link them to users
db.define_table("user_token", Field("token"), Field("user_id", db.auth_user))

# we also create a storage where to put raw data
# in practice you want to use something more structured
db.define_table("dummy", Field("token"), Field("name"), Field("raw", "json"))


# let's create a fixture to check auth token exists
def get_token():
    return request.headers.get("Authentication")


class AuthTokenVerify(Fixture):
    def on_request(self, context):
        # response.headers = "Content-Type: application/json"
        token = get_token()
        if not db(db.user_token.token == token).count():
            raise HTTP(401)


auth_token_verify = AuthTokenVerify()

# put the id into the raw dict
def to_dict(item):
    if not item or not item.raw:
        return {}
    raw = dict(item.raw)
    raw["id"] = item.id
    return raw


# return records filetered by name and token
def my_stuff(name):
    return db(db.dummy.token == get_token())(db.dummy.name == name)


# select all records
@action("rest/<name>", method="GET")
@action.uses(db, auth_token_verify)
def rest(name):
    items = [to_dict(item) for item in my_stuff(name).select(cacheable=True)]
    print(items)
    return {"items": items}


# select one record
@action("rest/<name>/<id:int>", method="GET")
@action.uses(db, auth_token_verify)
def rest(name, id):
    token = request.headers.get("Authentication")
    item = my_stuff(name)(db.dummy.id == id).select(cacheable=True).first()
    return to_dict(item)


# create a record
@action("rest/<name>", method="POST")
@action.uses(db, auth_token_verify)
def rest(name):
    token = request.headers.get("Authentication")
    id = db.dummy.insert(token=get_token(), name=name, raw=request.json)
    return {"id": id}


# update a record
@action("rest/<name>/<id:int>", method="PUT")
@action.uses(db, auth_token_verify)
def rest(name, id):
    item = my_stuff(name)(db.dummy.id == id).select(cacheable=True).first()
    if item:
        raw = item.raw
        raw.update(**request.json)
        my_stuff(name)(db.dummy.id == id).update(raw=raw)
    return to_dict(item)


# delete a record
@action("rest/<name>/<id:int>", method="DELETE")
@action.uses(db, auth_token_verify)
def rest(name, id):
    my_stuff(name)(db.dummy.id == id).delete()
    return {}


@action("rest")
@action.uses("examples/rest_info.html", db)
def rest():
    new_token = str(uuid.uuid4())
    id = db.user_token.insert(token=new_token)
    # expire old user tokens
    db(db.user_token.id < max(1, id - 1000)).delete()
    return dict(token=new_token)

templates/examples/rest_info.html

[[extend "layout.html"]]

<h2>Rest examples</h2>

Your authentication token is <tt>[[=token]]</tt>.
Reload the page for a new token.

<h3>List all chairs</h3>
<pre>
    curl -H "Authentication: [[=token]]" \
         [[=URL('rest/chair', scheme=True)]]
</pre>

<h3>Create a new chair record</h3>
<pre>
    curl -X POST \
         -d '{"color":"red"}' \
         -H "Content-Type: application/json" \
         -H "Authentication: [[=token]]" \
         [[=URL('rest/chair', scheme=True)]]
</pre>

<h3>Retrieve chair with id=1</h3>
<pre>
    curl -H "Authentication: [[=token]]" \
         [[=URL('rest/chair/1', scheme=True)]]
</pre>

<h3>Update chair with id=1</h3>
<pre>
    curl -X PUT \
         -d '{"color":"green"}' \
         -H "Content-Type: application/json" \
         -H "Authentication: [[=token]]" \
         [[=URL('rest/chair/1', scheme=True)]]
</pre>

<h3>Delete chair with id=1</h3>
<pre>
    curl -X DELETE \
         -H "Authentication: [[=token]]" \
         [[=URL('rest/chair/1', scheme=True)]]
</pre>