3

Я использую Django в Google App Engine. Если у меня есть классИтерация над атрибутами модели при создании шаблона в Django

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

и у меня есть случай, когда Person.first_name = Боб и Person.last_name = Вэнс, я могу создать шаблон, который перебирает Лицо атрибутов для производства:

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

Возможно, более лаконично, существует ли метод model.as_table(), который будет распечатывать атрибуты моего экземпляра, Боб Вэнс?

+0

Да, вы можете! ___________ –

+0

ОК ... как? Мне было интересно, есть ли способ автоматически сделать ... для attr в attr (Person): но я не думаю, что python допускает итерацию атрибутов. – ehfeng

ответ

8

В шаблоне вы не можете получить доступ к атрибутам или функциям __underscored__. я предлагаю вместо этого вы создаете функцию в вашей модели/класс:

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__)] 

В шаблоне это просто:

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

Теперь это даст вам «first_name» вместо «First», но вы получите идея. Вы можете распространить метод быть Mixin или присутствовать в родительском классе и т.д .. Точно так же вы можете использовать это, если у вас есть несколько людей, объекты, которые вы хотите перебрать:

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

Не будете ли элементы в 'dict' выходить в непредсказуемом порядке? –

+0

Правильно, .. я добавил метод sorted_attrs. Я уверен, что есть лучший способ сделать это, но это быстрый взлом. Честно говоря, такой подход ошибочен в его корнях. Если вам нужно перебрать что-то, лучше использовать массив или другую структуру хранилища, а не атрибуты класса. – drozzy

2

Изменения:

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

к:

for attr, value in self.__dict__.iteritems(): 
+0

Дох, спасибо, исправлено сейчас. – drozzy

2

Наконец нашел хорошее решение для этого в списке рассылки DEV (http://groups.google.com/group/django-developers/browse_thread/thread/44cd834438cfda77/557f53697658ab04?lnk=gst&q=template+model#557f53697658ab04):

В окне просмотра оных:

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}) 

в шаблоне добавления:

{% for field in object %} 
    <li><b>{{ field.label }}:</b> {{ field.data }}</li> 
{% endfor %} 
0
def model_to_dict(instance, fields=None, exclude=None): 
    """ 
    Returns a dict containing the data in the ``instance`` where: 
    data = {'lable': 'verbose_name', 'name':name, 'value':value,} 
    Verbose_name is capitalized, order of fields is respected. 

    ``fields`` is an optional list of field names. If provided, only the named 
    fields will be included in the returned dict. 

    ``exclude`` is an optional list of field names. If provided, the named 
    fields will be excluded from the returned dict, even if they are listed in 
    the ``fields`` argument. 

    """ 

    data = [] 
    if instance: 
     opts = instance._meta 
     for f in opts.fields: 
      if not f.editable: 
       continue 
      if fields and not f.name in fields: 
       continue 
      if exclude and f.name in exclude: 
       continue 

      value = f.value_from_object(instance) 

      # load the display name of choice fields 
      get_choice = 'get_'+f.name+'_display' 
      if hasattr(instance, get_choice): 
       value = getattr(instance, get_choice)() 

      # only display fields with values and skip the reset 
      if value: 
       if fields: 
        data.insert(fields.index(f.name), {'lable': f.verbose_name.capitalize(), 'name':f.name, 'value':value,}) 
       else: 
        data.append({'lable': f.verbose_name.capitalize(), 'name':f.name, 'value':value,}) 
    return data 

TODO

  1. Добавить поддержку @property украшенные функции