Adding REST to Django
Question:
I’ve got a Django application that works nicely. I’m adding REST services. I’m looking for some additional input on my REST strategy.
Here are some examples of things I’m wringing my hands over.
- Right now, I’m using the Django-REST API with a pile of patches.
- I’m thinking of falling back to simply writing view functions in Django that return JSON results.
- I can also see filtering the REST requests in Apache and routing them to a separate, non-Django server instance.
Please nominate one approach per answer so we can vote them up or down.
Answers:
I’m thinking of falling back to simply
writing view functions in Django that
return JSON results.
- Explicit
- Portable to other frameworks
- Doesn’t require patching Django
Scrap the Django REST api and come up with your own open source project that others can contribute to. I would be willing to contribute. I have some code that is based on the forms api to do REST.
I’m thinking of falling back to simply
writing view functions in Django that
return JSON results.
I would go with that ..
Ali A summed it pretty well.
The main point for me is beign explicit. I would avoid using a function that automatically converts an object into json, what if the object has a reference to a user and somehow the password (even if it’s hashed) go into the json snippit?
I ended up going with my own REST API framework for Django (that I’d love to get rid of if I can find a workable alternative), with a few custom views thrown in for corner cases I didn’t want to deal with. It’s worked out ok.
So a combination of 1 and 2; without some form of framework you’ll end up writing the same boilerplate for the common cases.
I’ve also done a few stand-alone APIs. I like having them as stand-alone services, but the very fact that they stand alone from the rest of the code leads to them getting neglected. No technical reason; simply out-of-sight, out-of-mind.
What I’d really like to see is an approach that unifies Django forms and REST APIs, as they often share a lot of logic. Conceptually if your app exposes something in HTML it likely wants to expose it programmatically as well.
you could try making a generic functions that process the data (like parand mentioned) which you can call from the views that generate the web pages, as well as those that generate the json/xml/whatever
Please note that REST does not just mean JSON results. REST essentially means exposing a resource-oriented API over native but full-fledged HTTP. I am not an expert on REST, but here are a few of the things Rails is doing.
- URLs should be good, simple names for resources
- Use the right HTTP methods
- HEAD, GET, POST, PUT, and DELETE
- Optionally with an override (form parameter ‘_method’ will override HTTP request-method)
- Support content-type negotiation via Accept request-header
- Optionally with an override (filename extension in the URL will override MIME-type in the Accept request-header)
- Available content types should include XML, XHTML, HTML, JSON, YAML, and many others as appropriate
For example, to get the native HTTP support going, the server should respond to
GET /account/profile HTTP/1.1
Host: example.com
Accept: application/json
as it would respond to
GET /account/profile.json HTTP/1.1
Host: example.com
And it should respond to
PUT /account/profile HTTP/1.1
Host: example.com
var=value
as it would respond to
POST /account/profile HTTP/1.1
Host: example.com
_method=PUT&var=value
For anyone else looking for a very decent, pluggable API application for Django, make sure you checkout jespern’s django-piston which is used internally at BitBucket.
It’s well maintained, has a great following and some cool forks which do things like add support for pagination and other authentication methods (OAuth is supported out of the box).
Updated to reflect that django-piston is no longer maintained.
You could take look at django-dynamicresponse, which is a lightweight framework for adding REST API with JSON to your Django applications.
It requires minimal changes to add API support to existing Django apps, and makes it straight-forward to build-in API from the start in new projects.
Basically, it includes middleware support for parsing JSON into request.POST, in addition to serializing the returned context to JSON or rendering a template/redirecting conditionally based on the request type.
My answer to the same question here: Framework for Implementing REST web service in Django
The short version is, have a look at https://github.com/jgorset/django-respite/ a REST framework in its early days, but we use it every day on client projects.
Tastypie is also a newly emerging REST framework for Django.
It has the same mindset as pistons, and removes a lot of boilerplate coding.
TastyPie looks quite interesting and promising. It goes well with Django.
I’ve got a Django application that works nicely. I’m adding REST services. I’m looking for some additional input on my REST strategy.
Here are some examples of things I’m wringing my hands over.
- Right now, I’m using the Django-REST API with a pile of patches.
- I’m thinking of falling back to simply writing view functions in Django that return JSON results.
- I can also see filtering the REST requests in Apache and routing them to a separate, non-Django server instance.
Please nominate one approach per answer so we can vote them up or down.
I’m thinking of falling back to simply
writing view functions in Django that
return JSON results.
- Explicit
- Portable to other frameworks
- Doesn’t require patching Django
Scrap the Django REST api and come up with your own open source project that others can contribute to. I would be willing to contribute. I have some code that is based on the forms api to do REST.
I’m thinking of falling back to simply
writing view functions in Django that
return JSON results.
I would go with that ..
Ali A summed it pretty well.
The main point for me is beign explicit. I would avoid using a function that automatically converts an object into json, what if the object has a reference to a user and somehow the password (even if it’s hashed) go into the json snippit?
I ended up going with my own REST API framework for Django (that I’d love to get rid of if I can find a workable alternative), with a few custom views thrown in for corner cases I didn’t want to deal with. It’s worked out ok.
So a combination of 1 and 2; without some form of framework you’ll end up writing the same boilerplate for the common cases.
I’ve also done a few stand-alone APIs. I like having them as stand-alone services, but the very fact that they stand alone from the rest of the code leads to them getting neglected. No technical reason; simply out-of-sight, out-of-mind.
What I’d really like to see is an approach that unifies Django forms and REST APIs, as they often share a lot of logic. Conceptually if your app exposes something in HTML it likely wants to expose it programmatically as well.
you could try making a generic functions that process the data (like parand mentioned) which you can call from the views that generate the web pages, as well as those that generate the json/xml/whatever
Please note that REST does not just mean JSON results. REST essentially means exposing a resource-oriented API over native but full-fledged HTTP. I am not an expert on REST, but here are a few of the things Rails is doing.
- URLs should be good, simple names for resources
- Use the right HTTP methods
- HEAD, GET, POST, PUT, and DELETE
- Optionally with an override (form parameter ‘_method’ will override HTTP request-method)
- Support content-type negotiation via Accept request-header
- Optionally with an override (filename extension in the URL will override MIME-type in the Accept request-header)
- Available content types should include XML, XHTML, HTML, JSON, YAML, and many others as appropriate
For example, to get the native HTTP support going, the server should respond to
GET /account/profile HTTP/1.1
Host: example.com
Accept: application/json
as it would respond to
GET /account/profile.json HTTP/1.1
Host: example.com
And it should respond to
PUT /account/profile HTTP/1.1
Host: example.com
var=value
as it would respond to
POST /account/profile HTTP/1.1
Host: example.com
_method=PUT&var=value
For anyone else looking for a very decent, pluggable API application for Django, make sure you checkout jespern’s django-piston which is used internally at BitBucket.
It’s well maintained, has a great following and some cool forks which do things like add support for pagination and other authentication methods (OAuth is supported out of the box).
Updated to reflect that django-piston is no longer maintained.
You could take look at django-dynamicresponse, which is a lightweight framework for adding REST API with JSON to your Django applications.
It requires minimal changes to add API support to existing Django apps, and makes it straight-forward to build-in API from the start in new projects.
Basically, it includes middleware support for parsing JSON into request.POST, in addition to serializing the returned context to JSON or rendering a template/redirecting conditionally based on the request type.
My answer to the same question here: Framework for Implementing REST web service in Django
The short version is, have a look at https://github.com/jgorset/django-respite/ a REST framework in its early days, but we use it every day on client projects.
Tastypie is also a newly emerging REST framework for Django.
It has the same mindset as pistons, and removes a lot of boilerplate coding.
TastyPie looks quite interesting and promising. It goes well with Django.