Django: шаблон словаря / перекрестная ссылка на объект - PullRequest
1 голос
/ 07 августа 2011

В Django точка в шаблонной переменной теоретически означает поиск , основанный на следующем порядке разрешения:

  • Словарь поиска. Пример: foo["bar"]
  • Поиск атрибутов. Пример: foo.bar
  • вызов метода. Пример: foo.bar()
  • Поиск по индексу списка. Пример: foo[bar]

из рендеринг контекста в django 1.2 (docs.djangoproject.com).

На самом деле:

вид

...
class Veggie(object):
    def __init__(self, name):
        self.name = name
veggies = {'a': Veggie('carrot'), 'b': Veggie('lettuce')}

basket = ['a', 'c', 'b']

return render_to_response('tpls/veggies.txt', 
        {'veggies': veggies, 'basket': basket},
        mimetype="text/plain")

шаблон

Veggie by basket order, showing name

{% for veg in basket %}
    {{ veg }}
    {{ veggies.veg.name }}
{% endfor %}

выход

Veggie by basket order, showing name

    a

    c

    b

В этом выводе нет вегетарианских имен.

Я думаю, что это не то, что Джанго говорит, что делает на банке. Я ценю, что могу Питер Харкинс «Тег шаблона Django для доступа к словарю» *1043* написать тег, чтобы решить эту проблему. Это безобразно.

Это без исправления для команды Django, согласно Билету Django 12486 , потому что "Намерение состоит в том, что шаблоны Django могут быть прочитаны и написаны непрограммистами, настолько сложными Логика должна заключаться в просмотре кода или пользовательских тегов шаблона (Люк Завод)

Я был бы признателен за несколько практических советов по написанию разборчивого шаблонного кода в этой ситуации (у меня много «овощей» разного рода для разыменования). Стоит ли отходить от Django, если у нас есть создатели шаблонов, которые - хм - знают, как выполнять поиск по словарю?

Ответы [ 3 ]

2 голосов
/ 08 августа 2011

Движок шаблонов Django рассматривает veg в вашем цикле for как строку, но вы пытаетесь использовать его как часть выражения. Хотя механизм шаблонов Django иногда является препятствием, то, что вы делаете, просто не проверяет. То, что вы хотите сделать, это получить атрибут veggies с именем, содержащимся в объекте veg, и точечная запись не работает таким образом ни в Python, ни в шаблонах Django. Когда вы говорите veggies.veg, он ищет в овощах атрибут с именем veg, а не с именем a, b или c. Это не недостаток шаблонного движка Django; именно так работает Python (и все языки, которые мне известны).

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

1 голос
/ 08 августа 2011

Django способ сделать это состоит в том, чтобы подготовить структуры данных для рендеринга в представлении (я думаю, что это одна из причин, почему «представление» называется «представлением» в django), например,

basket = [veggies[veg_id] for veg_id in basket_id_list]

а затем

{% for veg in basket %}
    {{ veg.name }}
{% endfor %}

Итак, передайте структуры, которые вы хотите визуализировать, а не структуры, которые вы где-то получили.Неверно, что django считает авторов шаблонов глупыми людьми, неспособными понять поиск по словарю (или, например, немного кода на python), django считает, что поиск по переменному словарю (а также произвольный код на python) слишком сложен для логики шаблона, и есть причиныдля этого.Лично я не нашел ваш фрагмент кода шаблона очень читабельным, но это личные предпочтения.

Если вы не согласны с этой идеологией или она ограничивает вашу задачу, тогда легко использовать шаблонный фильтр (нет никакого способа различить dct [var] и dct ['var'] с помощью dot-синтаксис в любом случае, и фильтр просто однострочный, нет смысла использовать его в самом django) или, если эта идеология действительно отвратительна, переключиться на другой движок шаблонов, такой как jinja2.

0 голосов
/ 08 августа 2011

Django не позволяет вам быстро взломать шаблон, чтобы решить вашу проблему, потому что он обеспечивает разделение между авторами шаблонов и авторами представлений. Представьте, что вы продали 10 000 различных овощей и сохранили их в таблице базы данных. Вы действительно хотите передать в шаблон словарь всех 10 000 овощей, чтобы включить то, что вы описываете?

Если бы вы строили этот пример с реальными моделями, а не с классами и словарями, у вас, вероятно, уже было бы то, что вы хотели: «корзина» была бы объектом со ссылкой внешнего ключа на «вегетарианец», так что basket_item.veggie будет обратитесь к строке в таблице Veggie (тьфу, каламбур не предназначен). Вы можете просто передать в корзину, и вегетарианские элементы будут заполняться по требованию при обращении из шаблона. Для эффективности вы можете в конечном итоге использовать .select_related при извлечении элементов корзины для предварительного заполнения вегетарианских элементов в одном запросе SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...