views:

421

answers:

3

I'm trying to iterate over a dictionary of model values in a Django template - I want to list the verbose_name of each model field alongside its value.

Here's what I have in models.py:

class Manors(models.Model):
    structidx = models.IntegerField(primary_key=True, verbose_name="ID")    
    county = models.CharField(max_length=5, null=True, blank=True, verbose_name="County")   

    def get_fields(self):
            d = {}
            #d["database"] = "pubs"
            #d["uid"] = "sa"
            for field in Manors._meta.fields:
                d[field.verbose_name(self)] = field.value_to_string(self)
            return d

And in views.py:

    manor_stats = Manors.objects.get(structidx__exact=id)
    return render_to_response('template.html', { 'place' : place, 'manor_stats' : manor_stats }, context_instance = RequestContext(request))

And in the template:

<h4>Statistics</h4>
<ul>
 {% for key, value in manor_stats.get_fields %}
 <li> {{ key }}: {{ value }} </li>
{% endfor %}
</ul>

But I just get a weird, distorted-looking list like:

u: i
d: a

It doesn't even work if I use hard-coded values in models.py (as shown commented out above).

What's wrong here? Been trying to work this out for hours:(

---------- UPDATED ---------------

Trying with

def get_fields(self):
        d = {}
        for field in Manors._meta.fields:
            d[field.verbose_name(self)] = { "verbose": field.verbose_name(self), "value": field.value_to_string(self) }
        return d

and in template:

<h4>Statistics</h4>
<ul>
 {% for key, value in manor_stats.get_fields %}
 <li> {{ key }}: {{ value }}</li>
{% endfor %}
</ul>

just produces a blank list....

A: 

You're getting the weird results because I think you're iterating over a string's characters. A for loop in django templates isn't the same as in python. Try using an object and iterating via property accessors for object in my objects and then use object.prop1 object.prop2 instead.

apphacker
sorry, i need a bit more explanation... you mean change get_fields to return an object? or get rid of get_fields altogether and return an object some other way? :(
AP257
Just change a line: d[field.verbose_name(self)] = { "verbose": field.verbose_name(self), "value": field.value_to_string(self) }
apphacker
Thank you - see my updated code above though, this just produces a blank list...
AP257
...is this what you meant, or am I still missing something? Do I need to change something in the template too?
AP257
Just tried {% for object in manor_stats.get_fields %} <li> {{ object.verbose }}: {{ object.value }}</li>{% endfor %} in the template in case that's what you meant, but still a blank list.
AP257
MattH has a good solution
apphacker
+2  A: 

To iterate a dictionary wouldn't you need:

<h4>Statistics</h4>
<ul>
 {% for key, value in manor_stats.get_fields.items %}
 <li> {{ key }}: {{ value }}</li>
 {% endfor %}
</ul>

But I'd suggest retrieving the dictionary from the function first:

Views.py:

    manor_stats = Manors.objects.get(structidx__exact=id).get_fields()
    return render_to_response('template.html', { 'place' : place, 'manor_stats' : manor_stats }, context_instance = RequestContext(request))

And then:

<h4>Statistics</h4>
<ul>
 {% for key, value in manor_stats.items %}
 <li> {{ key }}: {{ value }}</li>
 {% endfor %}
</ul>

But only because I'm not that familiar with how much dereferencing the templating system can do. Seeing as you know how to deference it you're saving the effort of having the renderer work it out.

MattH
A: 

Iterating over a dict yields its keys. I don't know why Django thinks you want to do an incomplete sequence expansion on the key name instead of throwing an exception, but I'll chalk it up to ANOTHER one of Django's template engine's quirks.

Anyways, yes, get key from the dict in your for loop, then use key and dict.key inside it.

Ignacio Vazquez-Abrams