RESTful Django practice
djangopythonrestfulAfter several rounds reading RESTfull Web Services, I still have feeble confidence on my understanding the hyped REST idea, so please never hesitate to criticize, suggest in the comment.
Expose the resources
A book can be easily be identified by ISBN or EAN, however, it may stand for the specific book other than other books, or it refers an eBook instance to for content presentation. We use an additional argument, format to differentiate them:
/bookshelf/books/(isbn|ean)?format=(pdf|chm|...|json)
UPDATE A better approach is to use the pseudo file:
/bookshelf/books/(isbn|ean)(.(pdf|chm|...|json))
The default format is JSON, the server will render the meta data and available eBook formats in JSON.
Client request | Server response |
---|---|
GET ../isbn(.pdf) | Book meta data and available formats, or the eBook data.
|
PUT ../isbn |
|
PUT ../isbn.pdf |
|
HEAD ../isbn | Available formats.(obsolete)
|
HEAD ../isbn.pdf | The content length and other information about the file.
|
DELETE ../isbn |
|
DELETE ../isbn.pdf |
|
Furthermore, the URL representation is supposed to be discoverable. So we add two boring URL:
Client request | Server response |
---|---|
GET /bookshelf/ | Available list, currently only books supported. |
GET /bookshelf/books | All books with pagination, ?page=n |
Serialization
There exists a generic RESTful Django project, django-rest-interface, no surprise it takes the built-in JSON serializer.
The default JSON serializer is convenient, but from my understanding, it is more or less gears towards the round trip of data serialization, while we favor presentation only:
- Too much database details exposed to the end users.
- ForeignKey and ManyToMany are interpreted as external link using the id field.
Furthermore, the JSON serializer is not lazy enough: the data has to be fetched from the database and stored in the memory before it is dumped to the stream. This may result in a serious scaling issue. The side-effect of the writing policy make it impossible to serialize in a recursive fashion, just because the stream has not been flushed until all the objects have been addressed. Otherwise, the ForeighKey and ManyToMany can be easily addressed. A better solution is to take the similar approach as SAX does. The tags are emitted recursively once a new object needs to be serialized.
We will discuss the Pattee’s implementation next time.