Modèles Django: parcourir et imprimer toutes les propriétés d'un objet?

j'ai un objet de base de données appelé , avec environ 30 champs. Pour la plupart des lignes, la plupart de ces champs sera nulle.

dans mon modèle, j'aimerais passer en boucle tous les champs de la rangée, et imprimer des informations pour seulement les champs qui ne sont pas nuls.

par exemple, il y a un champ appelé "nom": j'aimerais imprimer <li>Name: {{ manor_stats.name }}</li> dans le modèle seulement pour les objets où le champ n'est pas null. Idéalement, je voudrais tirer dans "Nom:" de quelque part aussi automatiquement, plutôt que le précisant.

je sais que je pourrais utiliser {% if manor_stats.name %} à vérifier si chaque champ est null, mais je ne veux pas le faire 30 fois pour tous les champs.

voici ce que j'ai en views.py:

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

et puis en place.html, je voudrais avoir quelque chose qui fonctionne à peu près comme ceci (pseudocode, avec ??? indiquant les bits que je ne sais pas comment faire):

{% if manor_stats %} 
<ul>
 {% for manor_stats.property??? in manor_stats %} 
  {% if manor_stats.property %} 
   <li>{{ manor_stats.property.field_name??? }} {{ manor_stats.property.value??? }}</li>
  {% endif %}
 {% endfor %
{% endif %}

l'Espoir qui fait sens...

22
demandé sur AP257 2010-02-07 20:07:37

3 réponses

vous pouvez ajouter une méthode à votre modèle Manors qui retournera toutes les valeurs de champ, de là vous pouvez simplement faire une boucle sur ces valeurs dans votre vérification de modèle pour voir si la valeur n'est pas nulle.

-- models.py

class Manors(models.Model)
  #field declarations

  def get_fields(self):
    return [(field.name, field.value_to_string(self)) for field in Manors._meta.fields]
{% for name, value in manor_stats.get_fields %}
  {% if value %}
    {{ name }} => {{ value }}
  {% endif %}
{% endfor %}
49
répondu buckley 2010-02-08 00:04:07

l'approche suivante nécessite seulement la définition d'un filtre de modèle personnalisé (voir la doc) - C'est plus aride que d'avoir à écrire ou copier une méthode dans chaque modèle pour lequel vous avez besoin de cette fonctionnalité.

-- my_app/templatetags/my_tags.py

from django import template

register = template.Library()

@register.filter
def get_fields(obj):
    return [(field.name, field.value_to_string(obj)) for field in obj._meta.fields]

Vous aurez besoin de redémarrer votre serveur pour obtenir les nouvelles étiquettes enregistrés et disponibles dans vos templates.

-- my_app/templates/my_app / my_template.html

{% load my_tags %}
<ul>
{% for key, val in object|get_fields %}
  <li>{{ key }}: {{ val }}</li>
{% endfor %}
</ul>

Testé Django 1.11.

NB: Depuis le ._meta est un attribut privé, sa fonctionnalité pourrait bien changer à l'avenir.

Merci aux autres réponses sur ce post qui m'a pris la plus grande partie du chemin, en particulier W. Perrin.

2
répondu Rob Simpson 2018-07-27 10:52:10

Utiliser Le Modèle._meta.get_fields () en code python.

>>> from django.contrib.auth.models import User
>>> User._meta.get_fields()
(<ManyToOneRel: admin.logentry>,
 <django.db.models.fields.AutoField: id>,
 <django.db.models.fields.CharField: password>,
 <django.db.models.fields.DateTimeField: last_login>,
 <django.db.models.fields.BooleanField: is_superuser>,
....

Dans le modèle, nous pouvons définir un filtre pour récupérer tous les champs.

├─my_app
│  │
│  ├─templatetags
│  │  │  my_filters.py
│  │

from django import template
register = template.Library()

@register.filter
def get_fields(obj):
    return obj._meta.get_fields()

{% for k,v in obj|get_fields %}
    <td> {{k}} </td>
{% endfor %}

Voir ce lien: https://docs.djangoproject.com/en/2.0/ref/models/meta/#retrieving-all-field-instances-of-a-model

0
répondu W.Perrin 2018-05-26 18:20:56