Определите переменные в шаблоне, основываясь на том, что пользователь является персоналом или нет - PullRequest
0 голосов
/ 09 ноября 2010

Я пытаюсь отобразить HTML-таблицу значений с примерно 20 столбцами, где, скажем, сотрудники видят один поднабор столбцов, а пользователи, не являющиеся сотрудниками, видят другой набор столбцов. Я могу захотеть определить другие типы пользователей позже. Сейчас у меня есть три статических строки заголовка, поэтому шаблон выглядит как

<table>
<tr>
  <th>Col A</th>
  {% if user.is_staff %}<th>Col B</th>{% endif %}
  ...
  {% if not user.is_staff %}<th>Col K</th>{% endif %}
</tr>
<tr>
  <td>Col A second header</td>
  {% if user.is_staff %}<td>Col B second header</td>{% endif %}
  ...
  {% if not user.is_staff %}<td>Col K second header</td>{% endif %}</tr>
<tr><td>Col A third header</td>  ...  </tr>

{% for obj in object_list %}
<tr>
  <td>{{ obj.col_a }}</td>
  {% if user.is_staff %}<td>{{ obj.col_b }}</td>{% endif %}
  ...
  {% if not user.is_staff %}<td>{{ obj.col_k }}</td>{% endif %}
</tr>
{% endfor %}</table>

Тем не менее, я нахожу non-DRY, так как каждый раз, если я хочу изменить, если тип пользователя может видеть столбец, я должен изменить его в 4 местах. Или, если я хочу определить несколько разных классов пользователей, мне придется иметь сложные операторы if. Я бы предпочел что-то вроде

 {% if show_col_a %}<td>{{obj.col_a }}</td>{{% endif %}

Где я могу определить в верхней части шаблона (или, возможно, в представлении), что user.is_staff может видеть show_col_a. Возможно ли что-то подобное? Я использую общий вид (object_list). Может, как-нибудь изменить всех пользователей, чтобы они имели атрибуты user.show_col_a, и сделать {% if user.show_col_a%}? Я не уверен, как добавить логические атрибуты для пользователей.

РЕДАКТИРОВАТЬ: может потребоваться несколько пользователей с настраиваемыми представлениями (например, staff_view; admin_view, непривилегированный и т. Д.), Так что если утверждения станут громоздкими. Содержимое ячейки обычно сложнее, чем {{obj.col_b}}; попытался упростить задачу, чтобы добраться до сути. E.g.:

<td>{% if obj.custom_address %}
  {{ obj.custom_address.webprint|safe }}
{% else %}
  {{ obj.business.address.webprint|safe }}
{% endif %}</td>

Кроме того, хотя несколько шаблонов будут работать с простым переключателем, например: {% if user.is_staff%} {% include "template_staff.html"%} {% else%} {% if user.is_admin%} {% include "template_admin.html"%} {% else%} {% include "template_other.html"%} {% endif%} {% endif%}

Я считаю, что это не СУХОЙ; например, каждое редактирование шаблона должно быть воспроизведено в трех шаблонах. Я думаю, я мог бы сделать скрипт, который читает, генерирует три шаблона из некоторого super_template вне django, но он становится очень не элегантным.

1 Ответ

2 голосов
/ 09 ноября 2010

Это во многом зависит от того, какой у вас вид и шаблоны.

Способы сделать:

  • сделать общедоступный шаблон и шаблон персонала и добавить простой метод для изменения шаблоновна лету для просмотра.
  • создайте тег шаблона:

    {% is_staff myvar%}

код тега:

class IsStaffNode(Node):
    def __init__(self, var):
        self.var = var

    def render(self, context):
        if context['user'].is_staff():
            return var.resolve(context)
        return ""


@register.tag
def is_staff(parser, token):
    var = parser.compile_filter(token.split_contents()[1])
    return IsStaffNode(var)

Домашнее задание: сделайте его блочным тегом, чтобы включить тд, чтобы он отображался либо все, либо ни одного.

{% isstaff myvar %}<td>{{ myvar }}</td>{% endisstaff %}

Этот способ более трудоемкий, чем 2 разных шаблона, но еслихочу попробовать, манипулируя контекстом (или создавая отдельный контекст только для блока) может быть полезно .

  • Создать процессор контекста, который бы заполнил контекст некоторыми переменными, еслипользователь является персоналом или нет, если нет.
  • Создайте тег, который будет включать шаблон (наследование от IncludeNode) и управлять контекстом.
...