Django
템플릿 태그 및 필터
수색…
맞춤 필터
필터를 사용하면 변수에 함수를 적용 할 수 있습니다. 이 함수는 0 또는 1 인수를 취할 수 있습니다. 구문은 다음과 같습니다.
{{ variable|filter_name }}
{{ variable|filter_name:argument }}
필터가 연결되어있어 이것이 완벽하게 유효합니다.
{{ variable|filter_name:argument|another_filter }}
파이썬으로 변환하면 위의 줄은 다음과 같이됩니다 :
print(another_filter(filter_name(variable, argument)))
이 예제에서는 모델 (인스턴스 또는 클래스) 또는 QuerySet에 적용되는 사용자 정의 필터 verbose_name
을 작성합니다. 인수가 True
로 설정된 경우 모델의 자세한 이름 또는 자세한 이름이 plural을 반환합니다.
@register.filter
def verbose_name(model, plural=False):
"""Return the verbose name of a model.
`model` can be either:
- a Model class
- a Model instance
- a QuerySet
- any object refering to a model through a `model` attribute.
Usage:
- Get the verbose name of an object
{{ object|verbose_name }}
- Get the plural verbose name of an object from a QuerySet
{{ objects_list|verbose_name:True }}
"""
if not hasattr(model, '_meta'):
# handle the case of a QuerySet (among others)
model = model.model
opts = model._meta
if plural:
return opts.verbose_name_plural
else:
return opts.verbose_name
단순 태그
사용자 정의 템플리트 태그를 정의하는 가장 간단한 방법은 simple_tag
를 사용하는 것입니다. 이것들은 설정하기가 매우 쉽습니다. 함수 이름은 태그 이름이되며 (무시할 수는 있지만) 인수는 토큰 (따옴표로 묶인 공백을 제외하고 공백으로 구분 된 "단어")이됩니다. 심지어 키워드 인수를 지원합니다.
다음은 예제를 설명 할 쓸모없는 태그입니다.
{% useless 3 foo 'hello world' foo=True bar=baz.hello|capfirst %}
foo
와 baz
다음과 같은 컨텍스트 변수라고합시다.
{'foo': "HELLO", 'baz': {'hello': "world"}}
우리는 이처럼 쓸모없는 태그를 이렇게 렌더링하려고합니다.
HELLO;hello world;bar:World;foo:True<br/>
HELLO;hello world;bar:World;foo:True<br/>
HELLO;hello world;bar:World;foo:True<br/>
인수 연결의 종류가 3 번 반복되었습니다 (3이 첫 번째 인수 임).
태그 구현은 다음과 같습니다.
from django.utils.html import format_html_join
@register.simple_tag
def useless(repeat, *args, **kwargs):
output = ';'.join(args + ['{}:{}'.format(*item) for item in kwargs.items()])
outputs = [output] * repeat
return format_html_join('\n', '{}<br/>', ((e,) for e in outputs))
format_html_join
표시 할 수 있습니다 <br/>
의 내용을 안전 HTML을,하지만 outputs
.
노드를 사용하는 고급 사용자 정의 태그
가끔은 filter
나 simple_tag
대해 너무 복잡합니다. 이것을 사용하면 컴파일 기능과 렌더러를 만들어야합니다.
이 예제에서는 다음 구문으로 템플릿 태그 verbose_name
을 생성합니다.
예 | 기술 |
---|---|
{% verbose_name obj %} | 모델의 자세한 이름 |
{% verbose_name obj 'status' %} | 필드 "상태"의 자세한 이름 |
{% verbose_name obj plural %} | 복수형 모델의 복수형 |
{% verbose_name obj plural capfirst %} | 모델의 복수화 된 이름 복수형 |
{% verbose_name obj 'foo' capfirst %} | 필드의 이름이 대문자로 표기 됨 |
{% verbose_name obj field_name %} | 변수에서 필드의 자세한 이름 |
{% verbose_name obj 'foo'|add:'_bar' %} | 필드의 자세한 이름 "foo_bar" |
우리가 간단한 태그로 이것을 할 수없는 이유는 plural
과 capfirst
가 변수도 문자열도 아니며 "키워드"이기 때문입니다. 분명히 문자열을 'plural'
및 'capfirst'
문자열로 전달할 수 있지만이 이름을 가진 필드와 충돌 할 수 있습니다. {% verbose_name obj 'plural' %}
는 "자세한 이름 복수형 obj
"또는 "자세한 이름 obj.plural
"를 의미합니까?
먼저 컴파일 기능을 만듭니다.
@register.tag(name='verbose_name')
def do_verbose_name(parser, token):
"""
- parser: the Parser object. We will use it to parse tokens into
nodes such as variables, strings, ...
- token: the Token object. We will use it to iterate each token
of the template tag.
"""
# Split tokens within spaces (except spaces inside quotes)
tokens = token.split_contents()
tag_name = tokens[0]
try:
# each token is a string so we need to parse it to get the actual
# variable instead of the variable name as a string.
model = parser.compile_filter(tokens[1])
except IndexError:
raise TemplateSyntaxError(
"'{}' tag requires at least 1 argument.".format(tag_name))
field_name = None
flags = {
'plural': False,
'capfirst': False,
}
bits = tokens[2:]
for bit in bits:
if bit in flags.keys():
# here we don't need `parser.compile_filter` because we expect
# 'plural' and 'capfirst' flags to be actual strings.
if flags[bit]:
raise TemplateSyntaxError(
"'{}' tag only accept one occurrence of '{}' flag".format(
tag_name, bit)
)
flags[bit] = True
continue
if field_name:
raise TemplateSyntaxError((
"'{}' tag only accept one field name at most. {} is the second "
"field name encountered."
).format(tag_name, bit)
field_name = parser.compile_filter(bit)
# VerboseNameNode is our renderer which code is given right below
return VerboseNameNode(model, field_name, **flags)
그리고 이제 렌더러 :
class VerboseNameNode(Node):
def __init__(self, model, field_name=None, **flags):
self.model = model
self.field_name = field_name
self.plural = flags.get('plural', False)
self.capfirst = flags.get('capfirst', False)
def get_field_verbose_name(self):
if self.plural:
raise ValueError("Plural is not supported for fields verbose name.")
return self.model._meta.get_field(self.field_name).verbose_name
def get_model_verbose_name(self):
if self.plural:
return self.model._meta.verbose_name_plural
else:
return self.model._meta.verbose_name
def render(self, context):
"""This is the main function, it will be called to render the tag.
As you can see it takes context, but we don't need it here.
For instance, an advanced version of this template tag could look for an
`object` or `object_list` in the context if `self.model` is not provided.
"""
if self.field_name:
verbose_name = self.get_field_verbose_name()
else:
verbose_name = self.get_model_verbose_name()
if self.capfirst:
verbose_name = verbose_name.capitalize()
return verbose_name