Simple Desktops for the Mac!
I'm completely stoked that the Simple Desktops app for the Mac is now available in the App Store. I took over the reigns of site development from Kenny Meyers in early 2011. Since then, Tom Watson and I have been trucking along making a lot of small tweaks leading up to this app.
I introduced Tom to Justin Voss who by day is a Java Programmer at a very large Enterprise here in Columbia, MO, but by night is an amazing Cocoa and Django developer. The collaboration on this was a ball. Tom had the vision, Justin made it happen, and I gave Justin an API to interact with existing data.
All things considered, the API was stupid simple to implement, thanks to Django-Piston. Jesper at BitBucket gave Django developers are real gem by releasing this code. When it was all said and done, it was accomplished in under 50 lines of Python.
For anyone interesting in Piston, here's a bit of how I accomplished things. We have a RandomDesktopHandler which is pretty simple:
class RandomDesktopHandler(DesktopsHandler): def read(self, request): return Desktop.live.select_related().order_by("?")
What initially tripped me up was wanting to display fields in the API that weren't in the Desktop object. In order to facilitate previous/next desktop functionality in the Mac App, this is something we needed.
Basically, this is how we accomplished it:
from piston.handler import BaseHandler from desktops.models import Desktop class DesktopsHandler(BaseHandler): fields = ('pk', 'title', 'next_url', 'previous_url', ) model = Desktop def read(self, request): # read method @classmethod def next_url(cls, desktop): url = desktop.get_next() # grab the next live desktop if not url: return None return url.get_api_absolute_url() # previous_url here...
get_api_absolute_url() is a @models.permalink method on the desktop model. By making it a class method in the api handler, we are able to access it as a field in the API response.
The last bit that got us was caching. Piston/Django are sending 600 second cache headers, which are no good if we want truly random results. So we threw together a quick cache killer to use in the api urls file.
def cache_killer(view): def inner_view(request, *args, **kwargs): response = view(request, *args, **kwargs) response['Expires'] = 'Mon, 26 Jul 1997 05:00:00 GMT' response['Cache-Control'] = 'max-age=0, private, no-cache, no-store, must-revalidate, proxy-revalidate, no-transform' response['Pragma'] = 'no-cache' return response return inner_view
And with that, we get random results on every hit!
Being a paranoid sysadmin, this does makes me nervous. Will Postgres get beat to death? We have more than web traffic to worry about now. So I decided to throw Varnish in front of most of the pages for now. This helps to mitigate load on the database server, so everyone can live in harmony.
I'd be remiss if I didn't send huge props to on of my most favorite icon designers Louis Harboe. He totally killed the design of the apps icon. I'd also be way more of a wreck if the Desktops weren't on the EngineHosting CDN.
I hope your enjoy the initial offering. Go get it, rate it and let us know what you think. We have even more up our sleeve, so stay tuned.