Choosing an API framework for Django
pydanny.com
pydanny.com
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... , or to see the many tests for the code at https://bitbucket.org/jespern/django-piston/src/7c90898072ce...
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.
We run Django 1.3.1 / Piston 0.3dev / Git 1.7.6 / Hg 1.9.1 / Python 2.7.3
Presumably they use it for their APIs http://confluence.atlassian.com/display/BITBUCKET/Using+the+...See my article at http://pydanny.blogspot.com/2010/07/getting-piston-forms-to-... which STILL gets a lot of hits.
That django-piston is 'stable' means work outside of maintenance has ceased. Which means a lot of people are going to this post to figure out what django-piston should do out of the box.
> Critical Update 2012/05/10!!!
> Critical Update 2012/05/10!!!
> Critical Update 2012/05/10!!!
(I guess you wanted one line per exclamation point there)
> Except for a critical security patch, django-piston has been unsupported for about 3 years. That is an eternity, and the number of forks to address multiple issues is cause for alarm. Also, the original author has left the project. Because of that, in it's place at this time I recommend django-tastypie. It is up-to-date, has very good documentation, supports OAUTH, and scored second place in the Django Packages thunderdome (it got nearly 3x as many points!). Another tool to consider is Django Rest Framework, which is as good as django-tastypie but lacks the OAUTH support.
Good god, man.
And I had a different Critical Update on that blog post for over 10 months with a harsher warning. I changed it today because I still had seen no progress but felt I should tone it down.
If the django-piston community updates and documents, I'll post something nicer. In the meantime, the critical update remains.
When I first started investigating Piston I read almost every line of code that I was going to be using.
I'm glad I did!
Understanding Piston at the source level allowed me to create wrappers, mixins, and extensions that turned Piston into something that I was more comfortable with. I moved away from Piston (Piston lacks a few features that come baked-in by default w\ TP) to Tastypie, but, the experience was almost exactly the same.
I spent most of last week reading the Tastypie code and creating a tastypie_ext library that helps me do things my way and patch up a few of what I see as major issues (did you know that Tastypie will 500 by default if you pass it malformed json/yaml/xml? That is, client input can raise an unhandled exception on demand.)
As far as documentation goes, Tastypie isn't much better than Piston, and Django itself still has a few gaping holes in its documentation (I'm still waiting for better class-based view documentation before I adopt them completely.)
I tend to view frameworks and libraries as loaded guns... At the end of the day every person using a framework should understand how it works from top to bottom at the source level.
P.S. Thanks for django-uni-form (now django-crispy-forms)! I learned to use it by reading the source :D.
Nice story, but you forgot the obligatory YMMV warning.
Reading the code is not a substitute for good documentation.
The current PyPI release of Piston (0.2.3) is six months old. It's incompatible with the current release version of Django (1.4). That Django release has been available for a month and a half, and available in beta for three months. This does not indicate a project that's in active development. A project in active development would get a release out the door so that if I run
pip install django django-piston
I get two pieces of software that work together.
tl;dr: either documentation or cross-resource links will be broken - pick one. It's been broken for years. There is a kludge-around but it's a rake in the grass waiting for every user.
I also had a related issue which similarly means that a common Django feature breaks the documentation feature: https://bitbucket.org/jespern/django-piston/issue/142/handle...
I won't say piston is dead but I will say that my experience with tastypie is that something like this would be fixed in a day or two.
From https://github.com/samuelclay/NewsBlur/blob/master/utils/jso...:
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,
}So while it is very powerful, I probably won't be using it again for a large project.
(I know, I know, it's XML. But people still use it.)
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.
Well, i must say that tastypie is just more mature, reliable, documented and support-friendly.
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
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.
Thanks for the correction.
Swagger creates beautiful interactive sandboxes for REST APIs http://swagger.wordnik.com/