if..else пользовательский тег шаблона - PullRequest
8 голосов
/ 17 октября 2011

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

Теперь у меня есть (псевдокод):

{% check_permission request.user "can_edit" on article %}
    <form>...</form>
{% endcheck %}

('check_permission' - мой пользовательский тег шаблона).

Шаблон тега принимает пользователя, разрешение и экземпляр объекта и возвращает вложенный HTML-код (форму). В настоящее время это прекрасно работает.

Однако я хотел бы сделать что-то вроде:

{% if check_permission request.user "can_edit" on article %}
    <form>...</form>
{% else %}
    {{ article }}
{% endif %}

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

Ответы [ 4 ]

15 голосов
/ 17 октября 2011

Вы можете использовать фильтры шаблонов внутри операторов if.Таким образом, вы можете переписать свой тег в качестве фильтра:

{% if request.user|check_can_edit:article %}

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

14 голосов
/ 10 января 2013

Вы определенно можете сделать это, если хотите написать еще несколько строк кода на Python, чтобы улучшить читаемость шаблона!:)

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

Тег, реализованный ниже, можно использовать какэто:

{% load mytag %}
{% mytag True %}Hi{% else %}Hey{% endmytag %} Bro

Или с переменной:

{% mytag myobject.myflag %}Hi{% else %}Hey{% endmytag %} Bro

Итак, вот как я это сделал:

from django.template import Library, Node, TemplateSyntaxError

register = Library()

@register.tag
def mytag(parser, token):
    # Separating the tag name from the "test" parameter.
    try:
        tag, test = token.contents.split()
    except (ValueError, TypeError):
        raise TemplateSyntaxError(
            "'%s' tag takes two parameters" % tag)

    default_states = ['mytag', 'else']
    end_tag = 'endmytag'

    # Place to store the states and their values
    states = {}

    # Let's iterate over our context and find our tokens
    while token.contents != end_tag:
        current = token.contents
        states[current.split()[0]] = parser.parse(default_states + [end_tag])
        token = parser.next_token()

    test_var = parser.compile_filter(test)
    return MyNode(states, test_var)


class MyNode(Node):
    def __init__(self, states, test_var):
        self.states = states
        self.test_var = test_var

    def render(self, context):
        # Resolving variables passed by the user
        test_var = self.test_name.resolve(context, True)

        # Rendering the right state. You can add a function call, use a
        # library or whatever here to decide if the value is true or false.
        is_true = bool(test_var)
        return self.states[is_true and 'myvar' or 'else'].render(context)

И это все.НТН.

0 голосов
/ 22 января 2019

В Django 2 тег назначения был заменен simple_tag (), но вы можете сохранить результат пользовательского тега как переменную шаблона:

# I'm assuming that check_permission receives user and article,
# checks if the user can edit the article and return True or False
{% check_permission user article as permission_cleared %}
{% if permission_cleared %}
    <form>...</form>
{% else %}
    {{ article }}
{% endif %}

Проверить текущий документ о пользовательских тегах шаблона: https://docs.djangoproject.com/en/2.1/howto/custom-template-tags/#simple-tags

0 голосов
/ 19 сентября 2018

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

Внутренний шаблонный тег

register = template.Library()
def exam_available(user, skill):
    skill = get_object_or_404(Skill, id=skill)
    return skill.exam_available(user)
register.filter('exam_available', exam_available)

Внутренний шаблон

    {{ request.user|exam:skill.id  }}
    or
    {% if request.user|exam:skill.id  %}

Так как один из основных общихэто использование request.user или любого конкретного объекта (id) внутри пользовательского метода модели, поэтому фильтрация этого отдельного объекта или пользователя является самым простым способом сделать это.:)

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