{ "info": { "author": "Zachary Voase", "author_email": "z@zacharyvoase.com", "bugtrack_url": null, "classifiers": [], "description": "# Dagny\n\nDagny is a [Django][] adaptation of [Ruby on Rails][]\u2019s Resource-Oriented\nArchitecture (a.k.a. \u2018RESTful Rails\u2019). \nDagny makes it *really easy* to build **resourceful** web applications.\n\n [django]: http://djangoproject.com/\n [ruby on rails]: http://rubyonrails.org/\n\nYou can read the full documentation [here](http://zacharyvoase.github.com/dagny/).\n\nAt present, this project is in an experimental phase, so APIs are very liable to\nchange. **You have been warned.**\n\nP.S.: the name is [a reference][dagny taggart].\n\n [dagny taggart]: http://en.wikipedia.org/wiki/List_of_characters_in_Atlas_Shrugged#Dagny_Taggart\n\n\n## Motivation\n\nRails makes building RESTful web applications incredibly easy, because\nresource-orientation is baked into the framework\u2014it\u2019s actually harder to make\nyour app *un*RESTful.\n\nI wanted to build a similar system for Django; one that made it incredibly\nsimple to model my resources and serve them up with the minimum possible code.\n\nOne of the most important requirements was powerful yet simple content\nnegotiation: separating application logic from the rendering of responses makes\nwriting an API an effortless task.\n\nFinally, as strong as Rails\u2019s inspiration was, it still needed to be consistent\nwith the practices and idioms of the Django and Python ecosystems. Dagny doesn\u2019t\nuse any metaclasses (yet), and the code is well-documented and readable by most\nPythonista\u2019s standards.\n\n\n## Appetizer\n\nDefine a resource:\n\n from dagny import Resource, action\n from django.shortcuts import get_object_or_404, redirect\n from polls import forms, models\n \n class Poll(Resource):\n \n @action\n def index(self):\n self.polls = models.Poll.objects.all()\n \n @action\n def new(self):\n self.form = forms.PollForm()\n \n @action\n def create(self):\n self.form = forms.PollForm(self.request.POST)\n if self.form.is_valid():\n self.poll = self.form.save()\n return redirect(\"Poll#show\", self.poll.id)\n \n return self.new.render()\n \n @action\n def edit(self, poll_id):\n self.poll = get_object_or_404(models.Poll, id=int(poll_id))\n self.form = forms.PollForm(instance=self.poll)\n \n @action\n def update(self, poll_id):\n self.poll = get_object_or_404(models.Poll, id=int(poll_id))\n self.form = forms.PollForm(self.request.POST, instance=self.poll)\n if self.form.is_valid():\n self.form.save()\n return redirect(\"Poll#show\", self.poll.id)\n \n return self.edit.render()\n \n @action\n def destroy(self, poll_id):\n self.poll = get_object_or_404(models.Poll, id=int(poll_id))\n self.poll.delete()\n return redirect(\"Poll#index\")\n\nCreate the templates:\n\n \n
Name: {{ self.poll.name }}
\n \n \n \n \n\nSet up the URLs:\n\n from django.conf.urls.defaults import *\n from dagny.urls import resources\n \n urlpatterns = patterns('',\n (r'^polls/', resources('polls.resources.Poll', name='Poll')),\n )\n\nDone.\n\n\n## Example Project\n\nThere\u2019s a more comprehensive [example project][] which showcases a user\nmanagement app, built in very few lines of code on top of the standard\n`django.contrib.auth` app.\n\n [example project]: http://github.com/zacharyvoase/dagny/tree/master/example/\n\nTo get it running:\n\n git clone 'git://github.com/zacharyvoase/dagny.git'\n cd dagny/\n pip install -r REQUIREMENTS # Installs runtime requirements\n pip install -r REQUIREMENTS.test # Installs testing requirements\n cd example/\n ./manage.py syncdb # Creates db/development.sqlite3\n ./manage.py test users # Runs all the tests\n ./manage.py runserver\n\nThen just visit