Hacker News new | past | comments | ask | show | jobs | submit login
REST framework 2 released: Simple, beautiful, browsable Web APIs for Django (django-rest-framework.org)
153 points by tomchristie on Oct 30, 2012 | hide | past | favorite | 58 comments



If you're looking for a framework for creating REST APIs in Django, TastyPie is also worth a look.

https://github.com/toastdriven/django-tastypie


+1. We started with django rest framework and it was a disaster.

The class-based approach gave very little practical reuse, and it was not granular enough to allow us to easily add validation rules or customize the fields to return from a model. Lots of ugly code where you had to concern yourself with response codes.. I mean whats the point with a framework if you have to concern yourself with response codes? Isn't it the frameworks role to abstract away these details?

Most of my beef with the framework has to do with the design. It has abstraction in all the wrong places ... Inversion of Control (IoC) just seem like a complete afterthought in the entire design.

Now with Tastypie, I will admit it has a steep learning curve, and a conceptual overhead, but it does a much better job of abstracting away the internals and you end up with a much more correct and consistent REST implementation. In addition, it is better architected which makes it easier to extract base classes and override behavior, which is valuable if you need it to work really well with non DB models.

I will say that deep down I'm not really happy with either alternatives though. Tastypie requires too much code to get up and running and it takes too much time to get confident with it. Will def. take a look at the other frameworks mentioned in this discussion.


Seriously, take a look a 2.0 - it's a huge, huge step up from the previous version, practically every aspect has been reworked and redesigned.

The initial version made some design compromises in order to support the Browseable API, and didn't take full advantage of Django's generic CBV's. (Since it was released when Django was still at 1.2) REST framework 2 fixes all that and much, much more.

I'd throughly recommend spending a while walking through the tutorial and taking a browse around the docs - I think you'll be pleasantly surprised.


Thanks - I'll take another look on the next project and see how it compares


I would seriously argue about granularity in tastypie. Anything more that default behavior and you have to override high level methods, and some times even copy paste implementation because there is no way to override


I would argue the contrary.. Maybe you can give some examples? - Are you overriding in the correct places? In the beginning with TastyPie, I would override get_detail and such, often when I should have been overriding obj_get instead..

We are using TastyPie in production on a pretty large site and I've been super happy with it. We have custom fields, custom auth, custom base classes for resources where the underlying data store are non django models, security is very granular (with minimal code overhead) and overall its been a blessing to extend and override. One thing I like in particular is how you can reuse nested Resource definitions, e.g. define a UserResource once and reuse it everywhere a model/resource has a FK to user and you get correct response output. Saves lots of time and gets you a correct, secure implementation.


I've used and like Tasty-Pie, but did find its magic in mapping models to endpoints a little too magical when I needed to build endpoints with even mildly complex filters/sorts/calculations. I was pretty quickly lost when digging through the code to figure out how tasty-pie did its magic. I recently selected rest-framework because, while it does provide help, it wasn't too magical and was fairly straightforward.


Very much so; when I was in the market for a REST app, I found tastypie very clean to work with for adding on to an existing project. (all the major options should be on djangopackages.com)


TastyPie is great for getting started, but scaling it is painful - out of the box, the queries it does are very inefficient.


How are they inefficient? I'm designing an app right now and am looking at different frameworks to use. Any recommendations?


Tasty-Pie is inefficient because if there are 20 resulting records to output from the API, if each record has 2 nested referenced records, TP will end up doing at least 60 queries, 1 query to hydrate each row + 1 query per nested record (but anecdotally for me it's been more like 100 queries to get 10 records due to redundant queries and other miscellaneous things happening). TP does no bulk query optimization and the result is /very/ high query volume.

I have cleaned up a lot of our Tasty-Pie backend and reduced query volume on endpoints which were 100+ queries down to be just 2 or 3 queries- but it was a tremendous amount of work with an ugly result from a complexity and architectural perspective.

I haven't found any Python-based API-in-a-box which I like.

OTOH, I've had much success with Scala + Play-framework + Squeryl - this combination gives fine grained explicit control over what is happening. This approach is generally very easy to scale. However this setup has it's own shortcomings- its always a tradeoff, right?

With Scala + Play, you don't get an API-in-a-box, so you must build it out yourself. It isn't particularly hard, but it definitely doesn't come "for free".

"for free", like TP- but it's only free at first because you will have to do complex and ugly hacks to make it scale.


I'm currently in the middle of a very similar situation. It's fine for dev, but throwing hundreds of queries at a single request just isn't going to scale.

We've ended up with stuff like:

     class Meta(SomeResource.Meta):
            cls = Challenge
     
            select_related_fields = [
                'category', 'owner', 'company', 'bonus', 'reward',
                ]
            prefetch_related_fields = [
                'specialities', 'countries',
                'companies', 'products',
                'groups',
                ]
     
            queryset = (cls.objects
                        .select_related(*select_related_fields)
                        .prefetch_related(*prefetch_related_fields)
                        .all())
which takes some of the pain away, but going through and profiling exactly which prefetches & joins help is a major hassle.

Resources with relations with full=True are also brutal. Manually stuffing only the required extra data speeds things up greatly, but there's too much boilerplate for my liking. Having some level in-between 'full' and 'resource-uri only' would be nice, but I haven't seen any nice way to do it.


These are the problems you have with any Django app as you learn to scale it, they're not inherent to Tastypie. They're why prefetch_related and select_related exist, you're Doing Things Right.


This isn't Right, IMO this is a sloppy mess of a way to develop a scalable API, and only lets you barely eek by. There is no joy.


I wish that I had a better response for this. I don't. Scaling is hard. It's work, It's not usually magic and you have to understand a lot about your system to get it right. Peppering in a few cache statements and figuring out the proper querysets isn't that bad. I know that I can't be seen as an impartial observer in this situation since I commit to Tastypie, but I got involved with the project because it did this stuff right. If you've got any suggestions on improvements I'm all ears and my email is in my profile


+1 - couldnt agree more.


Uhm.. sounds like your doing a bunch of N+1 querying, this is generally fixed by overriding get_query_set to use select_related in your manager classes and then you set .objects. to point to the overridden manager class inside of your models.


I just released a small REST API framework for Django as well: https://github.com/jarcoal/django-sliver

It's built entirely on CBVs, so if you're familiar with them, you will feel right at home.

The API is not frozen, so it's not production ready yet.


I'm fairly entrenched with Tastypie at the moment, but I've always been jealous of REST Framework's "document at the endpoint" setup.

Can I ask how you're determining whether or not the client is making an API call vs visiting the page directly? It'd be great to be able to supply Document templates that surface like REST Framework does, but I can't make out whether you're checking the client, the action, the protocol or something altogether different.


It uses the client's 'Accept:' header which specifies which media types it prefers for the response (eg. 'text/html', 'application/json')

Browsers will indicate that they prefer HTML, so that's what REST framework serves them.


So obvious, I'm embarrassed I didn't think of it first.

Much thanks!


Not happy with Tastypie[0] or DRF[1], we've created another one, basically a simple wrapper around CBVs, for a specific niche (RESTful but not HATEOAS, JSON-only): https://github.com/dobarkod/django-restless (overview&docs at http://django-restless.readthedocs.org/en/latest/ )

So far used it in a couple of our projects, but would welcome feedback.

[0] too much ModelResource magic [1] custom model (de)serialization into multiple formats, browsable api is majority of the framework: IAGNI, and 80% functionality we needed was in 20% of DRF (which is basically what Restless is)


As Tastypie has already been mentioned, and as it's probably REST Framework 2's main competitor – how do the two compare?


I still think Flask a much better choice for RESTful APIs when it comes to Python. It's a lot more lightweight, and companies like Twilio have done a lot to make building APIs with Flask very easy: http://flask-restful.readthedocs.org/en/latest/


Any chance we can add 'Django' to the front of the title please? 'REST framework 2 released' is a little misleading. The article is titled 'Django REST framework 2' any, so it would be more consistent anyway.


Note that there's a live version of the tutorial project available for testing here: http://restframework.herokuapp.com/


OT?: I wish the tutorial were better. It starts out with maximum complexity (minimal usage of the framework) and then reduces complexity. I skipped to the last page to try to see if DRF would actually save me time.

Compare to TastyPie where a functional API is built with very few lines of code and right near the top of the tutorial: http://django-tastypie.readthedocs.org/en/latest/tutorial.ht...


Personally, I like the approach of the tutorial.

It starts with the amount of code you would usually write if you were to write an API by hand and then simplifies things along the road. At the end it makes it clear how the framework can be simple to use while you've learned how to use it behind the hood if the magic needs tweaking.


"Most people just make the mistake that it should be simple to design simple things. In reality, the effort required to design something is inversely proportional to the simplicity of the result."

Sort of off-topic, but did Mr. Fielding mean to say either "inversely proportional to the complexity" or "proportional to the simplicity"? This quote implies that as effort increases, simplicity decreases, which seems out of spirit with the context of the quote.


No. Simple things are hard to create.


Yes, we understand what he means to say, but his words say the opposite.

He meant to say: "As effort increases, simplicity increases."

He instead said: "As effort increases, simplicity decreases."


This one is close to my heart at the moment. I'm not a big fan of Django in general as it's just too heavy for my needs but I've tried all the rest libs to try to get something that works for me. I haven't been completely happy with any of them.

So far the closet to happy I've been is with flask-restless - though I'm busy hacking around with that to get it working how I need (it's pretty feature light). It does mean I get to use SQL-Alchemy, which is every different kind of nice.

There's no doubt, designing a powerful and flexible api framework is a challenging job.

Will have a look at this now too, though. I'd definitely rather use something that has some development resource behind it instead of rolling my own.


I too wrote a REST app for Django http://bruth.github.com/restlib2/. I took the approach (which I speak about in the "Why?" section) to simply use the API terminologies HTTP already provides. Too many abstractions is a bad idea. For the curious, I've heavily documented Resources class: https://github.com/bruth/restlib2/blob/master/restlib2/resou... I've used it in production for quite some down now, but it is not yet complete.


I recently discovered REST framework for Python and... Twisted! It's so cute, I couldn't resist and actually used it to write a proxy for Google Refine reconciliation and url fetching functionality (for speedup and easier data manipulation) and it worked. Worked very well! Here it is for those interested: http://pypi.python.org/pypi/CorePost/0.0.16


A very much needed add-on for Django. It's cool to see the amount of work that's been put into making version 2 great!


This looks pretty good. I like that it leverages Django's CBVs. I couldn't tell from the docs if you could do queryset filtering though the URL's querystring (e.g http://api.example.com/blogs?author=10).


If using the generic CBVs you can override .get_queryset() to implement filtering just as you would with regular Django CBVs.

There's also an outstanding pull req to build in support for django-filter and other filtering backends which now just needs some docs, and which I plan to have merged in within the next few days or so. https://github.com/tomchristie/django-rest-framework/pull/29... That'll make it easier to do more complex filtering stuff. (And eventually have the filters be presented in the Browsable API)


I have a mixin that often use to do basic querystring filtering with CBVs, but it is nowhere near as comprehensive as http://django-tastypie.readthedocs.org/en/latest/resources.h....


Since everyone is sharing the django-rest framework they are using, I'll chime in with my choice:

Django-Piston

https://bitbucket.org/jespern/django-piston/wiki/Home

I have not used any other frameworks but will be trying ops suggestion.


Django-Piston is not longer being worked on. It may be risky to use a tool that isn't being regularly maintained.


How easy is it for me to upgrade? I have been using Django REST framework for a while and this upgrade path seems scary. I looked at the migration guide but it doesn't say anything about what I should be specifically concerned with.


There's so much work has gone into REST framework 2 that it's hard to present a single definitive migration guide. Best way to get an idea of migration plan would be to work your way through the tutorial first to get an idea of how everything fits together. You will need to put a little bit of work in, but it'll be time very well spent. Any questions at all just head over to https://groups.google.com/forum/?fromgroups#!forum/django-re... or try #restframework on freenode IRC.


We use DRF 1 for all our APIs. Very excited to give DRF 2 a whirl.


One newbie question: Why do I need a REST framework? I am able to create get/post APIs with what django offers. What would I need REST frameworks for django?


A couple of reasons I switched to entirely REST-based apps:

In case you want to provide an API to other users who aren't going to be making native Django calls.

In case your app is going to be based on Backbone (which maps models endpoints to REST endpoints, to oversimplify things.)

In case you need to consume your app from a mobile app, or external site, or whatever.

In case you want to surface your data in any way without having to give read/write access to the database directly -- you can implement REST and API Token authentication that maps to users so that they can read and write to the data that they have access to, but no more.


>API Token authentication

Could you give some pointers/links about how this is done?

I have used REST internally with no authentication. But I am not sure how these can be exposed to outside in a secure manner.


If you wanted to restrict all API access to only logged-in users (to your Django app), it would be as easy as this:

  from tastypie.authorization import DjangoAuthorization
and then in your 'Meta' class for each resource, you'd specify the following:

  authorization = DjangoAuthorization()
That's step one. To go further, and limit access to resources per user, so that they can only access the things they should have access to (according to Django permissions), you'd simply use 'apply_authorization_limits' to narrow the query object to what the user should have access to. So, if your default query looks like

  queryset = Resource.objects.all()
You could filter that down in your apply_authorization_limits method to something like this:

  def apply_authorization_limits(self, request, object_list):
    object_list.filter(user=request.user)


It solves a few problems like serialisation and enabling browsable APIs which makes it easier to both develop APIs and let others consume them. For me, the second part is more important than the first.


If you need to stick with Ruby for whatever reason, I recommend using Grape.

https://github.com/intridea/grape


Any chance any of these REST libs are going to support mongodb? If one already does, can someone provide a reference?


In addition to native Django ORM calls (to whatever DB you're using), we've also used tastypie to surface MongoDB and SOLR search results to REST endpoints.

Edit: I should mention that both were pretty painstaking the first go-around, but mostly due to my ignorance of the platform. I am thankful to know some more seasoned Tastypie users, so getting answers was pretty easy, and the Google Group is really good for Tastypie as well.


REST framework's serialization isn't tied to the ORM, so it should play perfectly well with mongodb.



I use it with mongoengine (drf 0.44). I only had to implement the resource serialization logic.

The framework is great, the best I have tried.


How easy would it be to hook this up to some sort of authentication scheme such as OAuth?


Pretty trivial. I'm planning on having integration with django-oauth2-provider added any day now.

Here's the outstanding ticket for OAuth: https://github.com/tomchristie/django-rest-framework/issues/... There's a link to a gist on there which implements that for REST framework 0.4, which just needs a little updating, testing, and documentation.


Aren't Class based views "restfull" in Django 1.5 ?


They provide some things that are useful for certain aspects of RESTfulness. Mainly making it easier to support the HTTP verbs properly, that's a very far from all there is to RESTful things though and that's where something like Django REST Framework comes in...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: