【问题标题】:Iterating over model attributes when creating a template in Django在 Django 中创建模板时迭代模型属性
【发布时间】:2010-11-13 10:48:10
【问题描述】:

我在 Google App Engine 中使用 Django。如果我有课

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

我有一个实例,其中 Person.first_name = Bob 和 Person.last_name = Vance,我可以创建一个模板来迭代 Person 属性以生成:

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

也许更简洁地说,是否有一个 model.as_table() 方法可以打印出我的实例 Bob Vance 的属性?

【问题讨论】:

  • 是的,你可以! ___________
  • 好的...怎么样?我想知道是否有一种方法可以自动执行... for attr in attr(Person): 但我认为 python 不允许迭代属性。

标签: django google-app-engine django-models django-templates


【解决方案1】:

在模板中你不能访问 __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 %}

【讨论】:

  • dict 中的项目不会以不可预知的顺序出现吗?
  • 对,.. 我添加了 sorted_attrs 方法。我确信有更好的方法可以做到这一点,但这是一个快速的黑客攻击。坦率地说,这种方法的根源是错误的。如果您需要迭代某些东西,最好使用数组或其他存储结构 - 而不是类的属性。
【解决方案2】:

终于在开发邮件列表(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 %}

【讨论】:

    【解决方案3】:

    变化:

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

    到:

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

    【讨论】:

      【解决方案4】:
      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
      

      待办事项

      1. 添加对 @property 修饰函数的支持

      【讨论】:

        猜你喜欢
        • 2015-10-24
        • 1970-01-01
        • 2011-03-24
        • 2013-03-25
        • 2015-12-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多