views:

1071

answers:

3

I'm using Django in Google App Engine. If I have the class

class Person():
    first_name = StringProperty()
    last_name = StringProperty()

and I have an instance where Person.first_name = Bob and Person.last_name = Vance, can I create a template that iterates over the Person attributes to produce:

<tr>
<td>First</td>
<td>Bob</td>
</tr>
<tr>
<td>Last</td>
<td>Vance</td>
</tr>

Perhaps more succinctly, is there a model.as_table() method that will print out the attributes of my instance, Bob Vance?

+6  A: 

In template you cannot access __underscored__ attributes or functions. I suggest instead you create a function in your model/class:

class Person(models.Model):
  first_name = models.CharField(max_length=256)
  last_name = models.CharField(max_length=256)

  def attrs(self):
     for attr, value in self.__dict__.iteritems():
        yield attr, value

 def sorted_attrs(self):
     # Silly example of sorting
     return [(key, self.__dict__[key]) for key in sorted(self.__dict__)]

In template it's just:

 <tr>
 {% for name, value in person.attrs %}
   <td>{{name}}</td> 
   <td>{{value}}</td>
 {% endfor %}
 </tr>

Now this will give you "first_name" instead of "First", but you get the idea. You can extend the method to be a mixin, or be present in a parent-class etc.. Similarly you can use this if you have a few person objects you want to iterate over:

{% for person in persons %}
 <tr>
 {% for name, value in person.attrs %}
   <td>{{name}}</td> 
   <td>{{value}}</td>
 {% endfor %}
 </tr>
{% endfor %}
drozzy
Wont the items in the `dict` come out in an unpredictable order?
Jack M.
Right,.. i added sorted_attrs method. I'm sure there is a better way of doing this, but this is a quickneasy hack.Frankly, this kind of approach is wrong at it's roots. If you need to iterate over something, it is better to use an array or other storage structure - not the attributes of the class.
drozzy
+1  A: 

I had to change:

for attr, value in a.dict.iteritems():

to:

for attr, value in self.dict.iteritems():

for the above code to work.

Ricklon
Doh, thanks, corrected now.
drozzy
A: 

Finally found a good solution to this on the dev mailing list (http://groups.google.com/group/django-developers/browse_thread/thread/44cd834438cfda77/557f53697658ab04?lnk=gst&amp;q=template+model#557f53697658ab04):

In the view add:

from django.forms.models import model_to_dict

def show(request, object_id):
    object = FooForm(data=model_to_dict(Foo.objects.get(pk=object_id)))
    return render_to_response('foo/foo_detail.html', {'object': object})

in the template add:

{% for field in object %}
    <li><b>{{ field.label }}:</b> {{ field.data }}</li>
{% endfor %}
Roger