53 votes

Effectuer une recherche de style getattr () dans un modèle django

La méthode getattr () de Python est utile lorsque vous ne connaissez pas à l'avance le nom d'un certain attribut.

Cette fonctionnalité serait également utile dans les modèles, mais je n'ai jamais trouvé de moyen de le faire. Existe-t-il une balise intégrée ou non intégrée qui peut effectuer des recherches d'attributs dynamiques?

72voto

fotinakis Points 804

J'ai également eu à écrire ce code comme un modèle personnalisé tag récemment. Pour gérer tous les look-up de scénarios, il est d'abord un attribut standard look-up, puis tente de faire un dictionnaire de recherche, puis tente un getitem de recherche (pour les listes de travail), puis suit la norme Django modèle de comportement quand un objet n'est pas trouvé.

(mise à jour 2009-08-26 à maintenant la poignée de l'indice de la liste des recherches ainsi)

# app/templatetags/getattribute.py

import re
from django import template
from django.conf import settings

numeric_test = re.compile("^\d+$")
register = template.Library()

def getattribute(value, arg):
	"""Gets an attribute of an object dynamically from a string name"""

	if hasattr(value, str(arg)):
		return getattr(value, arg)
	elif hasattr(value, 'has_key') and value.has_key(arg):
		return value[arg]
	elif numeric_test.match(str(arg)) and len(value) > int(arg):
		return value[int(arg)]
	else:
		return settings.TEMPLATE_STRING_IF_INVALID

register.filter('getattribute', getattribute)

Modèle d'utilisation:

{% load getattribute %}
{{ object|getattribute:dynamic_string_var }}


3voto

Daniel Naab Points 9857

Je ne pense pas. Mais il ne serait pas trop difficile d'écrire une balise de modèle personnalisée pour renvoyer un attribut dans le dict du contexte. Si vous essayez simplement de renvoyer une chaîne, essayez quelque chose comme ceci:

 class GetAttrNode(template.Node):
    def __init__(self, attr_name):
        self.attr_name = attr_name

    def render(self, context):
        try:
            return context[self.attr_name]
        except:
            # (better yet, return an exception here)
            return ''

@register.tag
def get_attr(parser, token):
    return GetAttrNode(token)
 

Notez qu'il est probablement tout aussi facile de le faire dans votre vue plutôt que dans le modèle, sauf s'il s'agit d'une condition qui se répète souvent dans vos données.

2voto

jamtoday Points 1811

J'ai fini par ajouter une méthode au modèle en question, et cette méthode est accessible comme un attribut dans le modèle.

Pourtant, je pense que ce serait génial si une balise intégrée vous permettait de rechercher dynamiquement un attribut, car c'est un problème que beaucoup d'entre nous ont constamment dans nos modèles.

2voto

Skylar Saveland Points 4131

Garder la distinction entre get et getattr,

 @register.filter(name='get')
def get(o, index):
    try:
        return o[index]
    except:
        return settings.TEMPLATE_STRING_IF_INVALID


@register.filter(name='getattr')
def getattrfilter(o, attr):
    try:
        return getattr(o, attr)
    except:
        return settings.TEMPLATE_STRING_IF_INVALID
 

0voto

mipadi Points 135410

Il n'y a pas de balise intégrée, mais il ne devrait pas être trop difficile d' écrire la vôtre .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X