views:

49

answers:

1

Hello folks. I've been getting lots of answers from stackoverflow now that I'm in Django just by searching. Now I hope my question will also create some value for everybody.

In choosing Django, I was hoping there was some similar mechanism to the way you can do partials in ROR. This was going to help me in two ways. One was in generating repeating indexed forms or form elements, and also in rendering only a piece of the page on the round trip.

I've done a little bit of that by using taconite with a simple URL click but now I'm trying to get more advanced. This will focus on the form issue which boils down to how to iterate over a secondary object.

If I have a list of photo instances, each of which has a couple of parameters, let's say a size and a quantity. I want to generate form elements for each photo instance separately. But then I have two lists I want to iterate on at the same time.

Context:

photos : Photo.objects.all()

and

forms = {}
for photo in photos:
  forms[photo.id] = PhotoForm()

In other words we've got a list of photo objects and a dict of forms based on the photo.id.

Here's an abstraction of the template:


{% for photo in photos %}
         {% include "photoview.html" %}
         {% comment %}
    So here I want to use the photo.id as an index to get the correct form.  So that each photo has its own form.  I would want to have a different action and each form field would be unique.  Is that possible?  How can I iterate on that?  Thanks!
Would it be a with?  In Python of course it's form = forms[photo.id] but here?
         {% endcomment %}
         
            Quantity: {{ oi.quantity }} {{ form.quantity }}
Dimensions: {{ oi.size }} {{ form.size }}
{% endfor %}

What can I do about this simple case. And how can I make it where every control is automatically updating the server instead of using a form at all?

Thanks!

James

A: 

I'm not sure I understand your question, but here's what I think you want, expressed in pseudo-code:

for photo in photos:
    form = forms[photo.id]
    generate_some_html(photo, form)

Probably the best way to achieve this is with inclusion tags: http://docs.djangoproject.com/en/dev/howto/custom-template-tags/#inclusion-tags . Basically, it's a custom tag that relies on another template, similar to an RoR partial. The details can be found in the link I provided, but what you basically need to do is

  1. create a package names "templatetags" in one of your app directories
  2. create a module in that package. Let's take foo_tags.py for example.
  3. Add the following boilerplate to foo_tags.py:

    from django import template
    register = template.Library()
    
  4. Write your custom tag, which implements generate_some_html. Make it take the caller's context:

    @register.inclusion_tag('relative/path/to/some/template.html', takes_context=True)
    def foo_tag(context):
        photo = context['photo']  # loop variable in parent template
        form = context['forms'][photo.id]
        # further computation that you need in order to setup the
        # context for relative/path/to/some/template.html can be
        # done here...
        return locals()
    
  5. Use the context returned by foo_tag in relative/path/to/some/template.html.

  6. Add {% load foo_tags %} to the parent template. You should probably put this near the top, the same way you put imports near the top of a .py file.
  7. Use your new custom tag in the parent template:

    {% for photo in photos %}
      {% foo_tag %}
    {% endfor %}
    
allyourcode
Wow, ok since I've not gone into custom tags yet, this will take some needed digesting! Thanks a ton! I'm looking forward to grappling with the concepts.
iJames