

Choosing an API framework for Django - pydanny
http://pydanny.com/choosing-an-api-framework-for-django.html

======
oinksoft
> I don't want to say anything negative, but let's face it: django-piston is
> dead.

Typical "I don't want to be rude or anything..." bullshit. Django Piston is
not a dead project. It is stable and not buggy, which may explain why there is
not a flurry of activity ... but even then, the project has a dozen commits in
the past six weeks.

Django ROA depends on Piston. Bitbucket is using Piston. Piston is not going
anywhere.

\---

Edit: A commenter on the blog voiced a similar opinion.

> Jon Morton:

> How is django-piston dead? it seems big websites like bitbucket are actively
> using it and it has had several recent commits:
> <https://bitbucket.org/jespern/..>.

>> pydanny:

>> Show me docs and test coverage improvements and I'll reconsider.

So, it seems we assess a project's liveliness by code coverage and thorough
documentation. Sounds like the author is wrong and is grasping for other
reasons to not like Piston. Of course, the fool's too lazy to find the docs
(right there on the project page) at [https://bitbucket.org/jespern/django-
piston/wiki/Documentati...](https://bitbucket.org/jespern/django-
piston/wiki/Documentation) , or to see the many tests for the code at
[https://bitbucket.org/jespern/django-
piston/src/7c90898072ce...](https://bitbucket.org/jespern/django-
piston/src/7c90898072ce/tests/test_project/apps/testapp/tests.py)

In short, don't listen to the author. People like him are the reason we'll
have three more web service libraries targeting Django within a year.

~~~
michaelmior
I'm curious where you saw that Bitbucket is using Piston. I'd be really
interested to hear where and how extensively.

~~~
andrewingram
Given that Piston was developed in-house at Bitbucket, it's hardly surprising.

~~~
michaelmior
Thanks for dropping that knowledge. I didn't realize :)

~~~
andrewingram
No worries, sorry if I came across as a bit dickish

------
conesus
There is a mention of `json.dumps` being too naive to be used in an API, and
there's good reason for that. If you want a more advanced JSON serializer for
Django, here's what I use on NewsBlur.

From
[https://github.com/samuelclay/NewsBlur/blob/master/utils/jso...](https://github.com/samuelclay/NewsBlur/blob/master/utils/json_functions.py):

    
    
        def json_encode(data, *args, **kwargs):
            """
            The main issues with django's default json serializer is that properties that
            had been added to an object dynamically are being ignored (and it also has 
            problems with some models).
            """
    
            def _any(data):
                ret = None
                # Opps, we used to check if it is of type list, but that fails 
                # i.e. in the case of django.newforms.utils.ErrorList, which extends
                # the type "list". Oh man, that was a dumb mistake!
                if hasattr(data, 'to_json'):
                    ret = data.to_json()
                elif isinstance(data, list):
                    ret = _list(data)
                # Same as for lists above.
                elif isinstance(data, dict):
                    ret = _dict(data)
                elif isinstance(data, Decimal):
                    # json.dumps() cant handle Decimal
                    ret = str(data)
                elif isinstance(data, models.query.QuerySet):
                    # Actually its the same as a list ...
                    ret = _list(data)
                elif isinstance(data, models.Model):
                    ret = _model(data)
                # here we need to encode the string as unicode (otherwise we get utf-16 in the json-response)
                elif isinstance(data, basestring):
                    ret = unicode(data)
                # see http://code.djangoproject.com/ticket/5868
                elif isinstance(data, Promise):
                    ret = force_unicode(data)
                elif isinstance(data, datetime.datetime) or isinstance(data, datetime.date):
                    ret = str(data)
                else:
                    ret = data
                return ret
        
            def _model(data):
                ret = {}
                # If we only have a model, we only want to encode the fields.
                for f in data._meta.fields:
                    ret[f.attname] = _any(getattr(data, f.attname))
                # And additionally encode arbitrary properties that had been added.
                fields = dir(data.__class__) + ret.keys()
                add_ons = [k for k in dir(data) if k not in fields]
                for k in add_ons:
                    ret[k] = _any(getattr(data, k))
                return ret
        
            def _list(data):
                ret = []
                for v in data:
                    ret.append(_any(v))
                return ret
        
            def _dict(data):
                ret = {}
                for k,v in data.items():
                    ret[str(k)] = _any(v)
                return ret
        
            ret = _any(data)
            return json.dumps(ret)
    

You can get the imports from the link above, but the point is that you want to
normalize any data structures into something that `json.dumps` can handle
easily. Things like datetimes, models, and querysets.

A trick that I use is to give each of my models a `Model.to_json()` method,
which looks something like this:

    
    
        def to_json(self):
            return {
                'date': self.date,
                'category': self.category,
                'title': self.title,
                'content': self.content,
                'with_user_id': self.with_user_id,
                'feed_id': self.feed_id,
                'content_id': self.content_id,
            }

------
richardlblair
I used django-tastypie to create our restful API at work. It turned into a
"round peg square hole" situation. In over half of my end points I had to over
ride the default behaviour. This goes right down to how URL are generated. I
spent a lot of time reading code.

So while it is very powerful, I probably won't be using it again for a large
project.

~~~
prayag
This is exactly my experience. When we were writing the first version of the
API for MobileWorks I chose django-tastypie. Within a few months we had
overridden most of the default behavior and a lot of my time was spent
studying the code-base of tasypie (which is fantastic BTW).

When it was time to write a new version, I decided to start from a clean slate
and write it ourselves from grounds-up. We don't have some of the
functionality that tasty-pie provided us out of the box but the maintenance
and new features are extremely fast to write.

~~~
richardlblair
We are about to do the exact same thing. Tastypie was a good decision to begin
with, but as our project evolves it becomes unrealistic.

------
dmishe
I decided to use rest-framework after using tastypie for some time. Primarily
because it seemed like less code and resources could be nested pretty easily,
which is strongly adviced agains in tastypie.

Well, i must say that tastypie is just more mature, reliable, documented and
support-friendly.

------
apendleton
One of the comments on the original post complains about extra boilerplate
with CBVs using django-rest-framework. I'll admit that I was concerned about
this as well, but after working with it for a while, I have to say that mixins
are a very natural pattern for API writing. You can string together a bunch of
them to get auth, pagination, etc., in a very clean way.

~~~
pydanny
I like the django-rest-framework CBV design, finding them much more elegant
(and documented) than Django's own CBVs.

------
dm8
Honest question - Why do you need API framework for Django? I've created APIs
for couple of Django products and never felt a need to use any framework. I
felt Django's MVC framework is robust for creating any APIs. May be using some
API framework will save some lines of code. But the joy of creating your own
stuff can beat that anytime.

------
senko
Using tastypie for two projects currently, it really is a great framework ..
for REST. But if you need a more RPCish style API (say, like what Twitter
has), it really is forcing a square peg into round hole and can get really
ugly.

------
jarcoal
I just started working with Tastypie, and am really enjoying it. I'm in the
process of writing an adapter to DynamoDB, and it's coming along very
smoothly.

------
streeter
django-tastypie is nice and new, but it does not yet handle file uploads
natively [1] which is why I went with django-piston for my project.

There is plans to support file uploads, but this was a deal breaker for my
API.

[1] <https://github.com/toastdriven/django-tastypie/issues/42>

------
bmelton
Also perhaps, is to choose Tastypie if you want API Key Authentication, and
Django-Rest-Framework if you want oAuth.

That's the reason I chose Tastypie over everything else, but I really like the
user-facing interface to Django-Rest better than I do Tastypie. Not enough to
forego our preferred authentication-schema mind you, but I wouldn't hate
having Class-based APIs either, but I haven't found that to be limiting in
Tastypie either.

Also, there's a Tastypie implementation for Mongo floating around out there
somewhere as well.

~~~
pydanny
django-rest-framework doesn't come with OAuth out of the box, django-tastypie
does. ;-)

~~~
bmelton
Gah, you're right -- I was thinking of something altogether different.

Thanks for the correction.

