Though I'm not a very big fan of Rails, I believe the one thing that it gets absolutely bang on the head is the conventions for RESTful resources. On a recent side project I am hacking on, I wanted to implement a nested resource structure and wanted to achieve URLs similar to what Rails would generate.

The crux of my problem was, that I had a nested resource, which could be attached to multiple parent models. Eg. say, a comment could be attached to a post, or, a photo. There is no standard way of doing this in Django. The approach I took is inspired by something I remember seeing in Pinax when it was still alive.

I'll explain the implementation with the Post and Comment model examples. Here the Post model is the parent resource, and Comment is the nested child resource which could be attached to it, and other models.

The urls that I would like are:

  1. posts/ - List of all posts
  2. posts/new - New post
  3. posts/<post id>/ - Post details
  4. posts/<post id>/edit - Edit post
  5. posts/<post id>/delete - Delete pst
  6. posts/<post id>/comments - All comments belonging to post
  7. posts/<post id>/comments/new - New comment belonging to post
  8. posts/<post id>/comments/<comment id> - Details of comment belonging to post
  9. posts/<post id>/comments/<comment id>/edit - Edit comment belonging to post
  10. posts/<post id>/comments/<comment id>/delete - Delete comment belonging to post

Lets first tackle the basic CRUD views for the Post model. With a little CBVfoo, inspired by this post, I was easily able to create views for 1-5 quite succintly.

The views for the Comment model are similar, but we need to override a few more methods.

Going over these methods one by one,

  1. get_queryset

    We use this to limit Comment objects belonging to the appropriate parent.

  2. get_template_names

    This allows us to override the default template names. Here we nest the templates under the app and model name of the parent model.

  3. form_valid

    Overriding this lets us attach the content object to the parent object

And finally, hooking all this up with the following urls, which is where a lot of the magic actually happens.

This is still my first draft at this, and so there might be a few bugs in this implementation. There is also a lot of code in the urls and the mixin that can be abstracted, but overall I'm quite happy with it.

Comments

comments powered by Disqus

About

Web Developer by day, Redditor by night and Browncoat for life. Geek. Origamist, FOSS Supporter, Avid Reader, Pythonista.

Currently hacking on python/django @dubizzle.