Выполнение поиска в стиле getattr () в шаблоне django - PullRequest
42 голосов
/ 10 мая 2009

Метод Pyat getattr () полезен, когда вы заранее не знаете имя определенного атрибута.

Эта функциональность также пригодится в шаблонах, но я никогда не придумал, как это сделать. Есть ли встроенный тег или не встроенный тег, который может выполнять динамический поиск атрибутов?

Ответы [ 6 ]

57 голосов
/ 11 июля 2009

Мне также недавно пришлось написать этот код в виде пользовательского тега шаблона. Для обработки всех сценариев поиска сначала выполняется поиск по стандартным атрибутам, затем выполняется поиск по словарю, затем выполняется поиск getitem (для работы списков), затем следует стандартному Django поведение шаблона, когда объект не найден.

(обновлено 2009-08-26, чтобы теперь также обрабатывать поиск по списку)

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

Использование шаблона:

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


2 голосов
/ 20 марта 2012

Сохраняя различие между get и 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
2 голосов
/ 10 мая 2009

Я закончил тем, что добавил метод к рассматриваемой модели, и к этому методу можно получить доступ как к атрибуту в шаблоне.

Тем не менее, я думаю, было бы замечательно, если бы встроенный тег позволял вам динамически искать атрибут, так как это проблема, которую многие из нас постоянно имеют в наших шаблонах.

2 голосов
/ 10 мая 2009

Я так не думаю. Но было бы не сложно написать пользовательский тег шаблона для возврата атрибута в контексте dict. Если вы просто пытаетесь вернуть строку, попробуйте что-то вроде этого:

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)

Обратите внимание, что, вероятно, так же легко сделать это в вашем представлении, а не в шаблоне, если только это условие не часто повторяется в ваших данных.

0 голосов
/ 15 января 2015

Этот фрагмент спас мой день, но мне нужно было, чтобы он охватывал отношения, поэтому я изменил его, чтобы разделить аргумент на «. и рекурсивно получить значение. Это можно сделать в одну строку: return getattribute(getattribute(value,str(arg).split(".")[0]),".".join(str(arg).split(".")[1:])) но я оставил его в 4 для удобства чтения. Я надеюсь, что кто-то использовал для этого.

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 AND recursively from a string name"""
    if "." in str(arg):
        firstarg = str(arg).split(".")[0]
        value = getattribute(value,firstarg)
        arg = ".".join(str(arg).split(".")[1:])
        return getattribute(value,arg)
    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
        return 'no attr.' + str(arg) + 'for:' + str(value)

register.filter('getattribute', getattribute)
0 голосов
/ 10 мая 2009

Нет встроенного тега, но не должно быть слишком сложно написать свой .

...