3

J'utilise Django dans Google App Engine. Si je la classeitération des attributs de modèle lors de la création d'un modèle dans Django

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

et j'ai une instance où Person.first_name = Bob et Person.last_name = Vance, puis-je créer un modèle qui itère sur la personne des attributs pour produire:

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

Peut-être plus succinctement, existe-t-il une méthode model.as_table() qui va imprimer les attributs de mon instance, Bob Vance?

+0

Oui, vous pouvez! ___________ –

+0

ok ... comment? Je me demandais s'il y avait un moyen de faire automatiquement ... pour attr dans attr (Personne): mais je ne pense pas que python permet l'itération des attributs. – ehfeng

Répondre

8

Dans le modèle, vous ne pouvez pas accéder aux attributs ou fonctions __underscored__. Je suggère au lieu de créer une fonction dans votre modèle/classe:

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

dans le modèle, il est juste:

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

Maintenant, cela vous donnera « prenom » au lieu de « First », mais vous obtenez l'idée. Vous pouvez étendre la méthode à un mixin, ou être présent dans une classe parente etc .. De même, vous pouvez l'utiliser si vous avez quelques personnes objets que vous voulez parcourir:

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

Les objets du dict ne sont-ils pas sortis dans un ordre imprévisible? –

+0

Droite, .. j'ai ajouté la méthode sorted_attrs. Je suis sûr qu'il y a une meilleure façon de le faire, mais c'est un hack quickneasy. Franchement, ce genre d'approche est mauvais à ses racines. Si vous avez besoin d'itérer sur quelque chose, il est préférable d'utiliser un tableau ou une autre structure de stockage - pas les attributs de la classe. – drozzy

2

Change:

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

à:

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

Doh, merci, corrigé maintenant. – drozzy

2

enfin trouvé une bonne solution pour cela sur la liste de diffusion de dev (http://groups.google.com/group/django-developers/browse_thread/thread/44cd834438cfda77/557f53697658ab04?lnk=gst&q=template+model#557f53697658ab04):

Dans le module complémentaire de vue:

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

dans le modèle ajouter:

{% 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. Ajout du support pour les fonctions décorées de @property