What is life like on the prairie? Well, under the right conditions it is like this:
About two months ago I rented a nice house a few miles outside Lawrence, Kansas. My original goal was to bike into town a few days every week. However, I'm leery of biking alone down rolling country roads so I bought myself a cheap little car. It gets me to and from Lawrence.
My fun new activity is Capoeira. It keeps me in shape and is something new and exciting for me to do. In order to support the Capoeira, I started up a local meetup. Yeah, at the extreme end of things you see some crazy acrobatics but for most people its the chance to have fun and get in shape. I should post some video online of my antics at Capoeira.
I'm also doing a bit of cooking. The kitchen in our house is really nice and I'm practicing my old culinary skills. My hope is to do a cook-off or a food camp with local friends at some point. Or maybe just relax and just cook for fun.
I tried a ballroom dance class in the area but was not happy with the quality of instruction. Also, that each class we learned a whole new dance form meant that you never really got comfortable with a single method. That said, I did learn some nice steps and hope to do them at a conference and found I really enjoy salsa.
The food here is generally cheap and good. Especially when it comes to core produce and meats. Getting some of the edgier ingredients means paying coastal prices or more. Fish and seafood seems to be hit or miss. I've heard the barbecue is outstanding but haven't been to any of the really notable places.
Life is a lot cheaper here. The dollar stretches amazingly far. My monthly rent on a really big house is a third of the cost of my mortgage or much less than what I was paying for a room in Arlington, Virginia. That means I do a few more of the things I really enjoy and also be able to save at a good rate.
Friday, July 30, 2010
Friday, July 16, 2010
Getting piston forms to play nicely with JSON
Critical Update 2012/05/10!!!
Critical Update 2012/05/10!!!
Critical Update 2012/05/10!!!
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.
Back to the existing blog post...
A commonly used tool by Djangonauts is django-piston, which is designed to make building a REST API easier. It even works with Django forms to provide easily written PUT/POST validation, which should be pretty darn nice. Unfortunately, if you go with django-piston forms validation it doesn't accomodate the JSON (or XML or YAML) requests and if validation fails it responds in HTML. Even more unfortunate, making validation accept and return JSON with PUT/POST requests is not documented.
While one could argue that it is documented in the django-piston docstrings, in my opinion that is not sufficient.
Fortunately while working on a project for Revolution Systems we worked out a solution:
""" myapi/resource.py author: Daniel Greenfeld license: BSD This assumes your API accepts JSON only. """ import json from piston.decorator import decorator from piston.resource import Resource from piston.utils import rc, FormValidationError def validate(v_form, operation='POST'): """ This fetches the submitted data for the form from request.data because we always expect JSON data It is otherwise a copy of piston.util.validate. """ @decorator def wrap(f, self, request, *a, **kwa): # Assume that the JSON response is in request.data # Probably want to do a getattr(request, data, None) # and raise an exception if data is not found form = v_form(request.data) if form.is_valid(): setattr(request, 'form', form) return f(self, request, *a, **kwa) else: raise FormValidationError(form) return wrap class Resource(Resource): def form_validation_response(self, e): """ Turns the error object into a serializable construct. All credit for this method goes to Jacob Kaplan-Moss """ # Create a 400 status_code response resp = rc.BAD_REQUEST # Serialize the error.form.errors object json_errors = json.dumps( dict( (k, map(unicode, v)) for (k,v) in e.form.errors.iteritems() ) ) resp.write(json_errors) return resp
Usage in handlers.py:
from django import forms from piston.handler import BaseHandler from myapp.models import Article # We use our custom validate rather than piston's default from myapi.resource import validate class ArticleForm(forms.Form): """ This is best stored in forms.py but we put here for sake of clarity""" author = forms.CharField(required=True) title = forms.CharField(required=True) content = forms.CharField(required=True) class ArticleHandler(BaseHandler): allowed_methods = ('GET', 'POST', 'PUT', 'DELETE', ) model = Article @validate(ArticleForm) def create(self, request): # Create/POST code goes here. @validate(ArticleForm) def update(self, request, id): # Update/PUT code goes here.
Usage in urls.py:
from django.conf.urls.defaults import * from piston.authentication import HttpBasicAuthentication as auth # Import our ArticleHandler from myapi.handlers import ArticleHandler # Use our custom Resource class instead of piston's default from myapi.resource import Resource article_handler = Resource(ArticleHandler, authentication=auth) urlpatterns = patterns('', url( r'^articles/(?P(\d+))$', article_handler, { 'emitter_format': 'json' }, name='api_article' ), )
Of course, this assumes you are mapping Create/Read/Update/Delete (CRUD) actions to your API.
I'm interested to see other solutions people have used to handle this in django-piston, and what suggestions people have that could improve on the examples I'm supplying here.
Friday, July 9, 2010
I want to talk to Jython and Iron Python developers
I want to ask some questions of the Jython and Iron Python communities. I'm primarily looking for efforts that can go into publishable case studies. Experience in use of Django in the Jython and Iron Python environments is also very much desired. Please use my email address which is obfuscated below and can be decoded by simply running the code in a python shell:
''.join([chr(x) for x in [112, 121, 100, 97, 110, 110, 121, 64, 103, 109, 97, 105, 108, 46, 99, 111, 109]])