Friday, May 04, 2007

inline_related_objects

[Edit, Feb 2008: fixed typo—changed extra_content to extra_context]

Today's neat Django trick: getting the create_update generic views for a model to display entries from a subsidiary model in-line—like the admin interface does when you add edit_inline=models.TABULAR.

The (oldforms) Form object that gets generated by the create_update view already has most of the required gubbins inside it; we just need a few extra steps to get at it:

  1. In urls.py, set an extra_context argument for the view to be a dictionary that contains inline_related_objects:
     {'inline_related_objects': model._meta.get_followed_related_objects(None) } 
  2. In the template, include a loop to pull in all of the related objects:
     {% for related_object in inline_related_objects %}{% edit_inline related_object %}{% endfor %} 
    within the <form> tag.
  3. Since the edit_inline template tag is not a built-in Django tag, the template also needs to load up the admin_modify extension:
     {% load admin_modify %} 
  4. Make local copies of the relevant admin templates (such as admin/edit_inline_tabular.html and widget/foreign.html) and tweak appropriately.

Of course, I didn't figure this out until after I'd spent a couple of hours dismantling the admin interface code with a view to stealing the relevant bits. Roll on the Django book.

2 comments:

AaronFay said...

Hey galloglass,

Still struggling with Django, can you give me an example of how to "set an extra_content argument for the view to be a dictionary that contains inline_related_objects"? I tried adding the code you mention to urls.py, in a couple different ways, I just get errors (on trunk).

Thanks,
Aaron

galloglass said...

Ah, oops, there's a typo. Should have said: extra_context. Sorry about that.


So a snippet from urls.py ended up like:

from django.contrib.admin.views.main import get_javascript_imports

in_type_opts = InType._meta #InType is one of my models

in_type_related_objects = in_type_opts.get_followed_related_objects(None)



# URL pattern

(r'^intype/(?P<object_id>\d+)/$', 'metatraq.data.views.object_update',

{ 'model' : InType,

'template_name': 'data/intype_update.html',

'extra_context': {'inline_related_objects': in_type_related_objects }}),

BTW, I've not done anything Djangoish recently, so I fell off the trunk a while ago—I don't know whether this stuff still works with more recent code.