Jinja: ๊ณต๋ฐฑ ์ œ์–ด์— ๋”ํ•˜๊ธฐ ๊ธฐํ˜ธ(+)๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ํƒœ๊ทธ ์ด๋ฆ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

์— ๋งŒ๋“  2017๋…„ 07์›” 15์ผ  ยท  5์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: pallets/jinja

์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘

trim_blocks ๊ฐ€ ํ•ญ์ƒ False ๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

lstrip_blocks ๊ฐ€ True ๋˜๋ฉด jinja๊ฐ€ ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

<!-- 1 -->
    <!-- 2 -->
foo<!-- 3 -->
<!-- 4 -->
<!-- 5 -->

๊ทธ๋ฆฌ๊ณ  False ์ด๋ฉด jinja๊ฐ€ ์ถœ๋ ฅ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    <!-- 1 -->
    <!-- 2 -->
    foo<!-- 3 -->
    <!-- 4 -->
    <!-- 5 -->

์‹ค์ œ ํ–‰๋™

๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘,

jinja2.exceptions.TemplateSyntaxError: ํƒœ๊ทธ ์ด๋ฆ„์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

ํ…œํ”Œ๋ฆฟ ์ฝ”๋“œ

    <!-- 1 -->
    {%+ if True %}<!-- 2 -->
    foo<!-- 3 -->
    {% endif %}<!-- 4 -->
    <!-- 5 -->

๋‹ค์Œ ํ…œํ”Œ๋ฆฟ์—๋„ ์œ ์‚ฌํ•œ ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

    <!-- 1 -->
    {% if True %}<!-- 2 -->
    foo<!-- 3 -->
    {%+ endif %}<!-- 4 -->
    <!-- 5 -->

์ „์ฒด ์—ญ์ถ”์ 

Traceback (most recent call last):
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1997, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1985, in wsgi_app
    response = self.handle_exception(e)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1540, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1982, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1614, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1517, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/_compat.py", line 33, in reraise
    raise value
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1612, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/app.py", line 1598, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
  File "/home/sunqingyao/PycharmProjects/microblog/app/views.py", line 22, in index
    posts=posts
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/flask/templating.py", line 133, in render_template
    return _render(ctx.app.jinja_env.get_or_select_template(template_name_or_list),
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/environment.py", line 869, in get_or_select_template
    return self.get_template(template_name_or_list, parent, globals)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/environment.py", line 830, in get_template
    return self._load_template(name, self.make_globals(globals))
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/environment.py", line 804, in _load_template
    template = self.loader.load(self, name, globals)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/loaders.py", line 125, in load
    code = environment.compile(source, name, filename)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/environment.py", line 591, in compile
    self.handle_exception(exc_info, source_hint=source_hint)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/environment.py", line 780, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/_compat.py", line 37, in reraise
    raise value.with_traceback(tb)
  File "/home/sunqingyao/PycharmProjects/microblog/app/templates/demo.html", line 2, in template
    {%+ if True %}<!-- 2 -->
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/environment.py", line 497, in _parse
    return Parser(self, source, name, encode_filename(filename)).parse()
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/parser.py", line 896, in parse
    result = nodes.Template(self.subparse(), lineno=1)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/parser.py", line 878, in subparse
    rv = self.parse_statement()
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/parser.py", line 125, in parse_statement
    self.fail('tag name expected', token.lineno)
  File "/home/sunqingyao/Envs/flask-mega/lib/python3.6/site-packages/jinja2/parser.py", line 59, in fail
    raise exc(msg, lineno, self.name, self.filename)
jinja2.exceptions.TemplateSyntaxError: tag name expected

๋‹น์‹ ์˜ ํ™˜๊ฒฝ

  • ํŒŒ์ด์ฌ ๋ฒ„์ „: 3.6.1+
  • Jinja ๋ฒ„์ „: Jinja2==2.9.6

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„, ์šฐ๋ฆฌ๋Š” ์ œํ•œ๋œ ์ž์œ  ์‹œ๊ฐ„์„ ๊ฐ€์ง„ ์ž์› ๋ด‰์‚ฌ์ž๋กœ์„œ ์ด๊ฒƒ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์˜์กดํ•˜์—ฌ ๋ถ„์„์„ ์ œ๊ณตํ•˜๊ณ  ํŒจ์น˜๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์—†์„ ๋•Œ ์ฑ„์šฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์˜ ์˜ํ–ฅ์„ ๋ฐ›๊ณ  ์ˆ˜์ •์— ๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ PR์„ ์ œ์ถœํ•˜์‹ญ์‹œ์˜ค.

๋ชจ๋“  5 ๋Œ“๊ธ€

์™œ ์ด๊ฒƒ์„ ๊ณ ์น  ๋™๊ธฐ๊ฐ€ ์—†์Šต๋‹ˆ๊นŒ?
์ฐธ์กฐ: https://stackoverflow.com/questions/35775207/remove-unnecessary-whitespace-from-jinja-rendered-template#35777386
์šฐ๋ฆฌ์˜ ๊ฒฝ์šฐ '-+' ์ฝค๋ณด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด {%... ์•ž์˜ ๊ณต๋ฐฑ์„ ํ”ผํ•˜๊ธฐ ์œ„ํ•ด ansible (jinja2-) ํ…œํ”Œ๋ฆฟ์—์„œ ์œ ์šฉํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค(๋กœ์ง๊ณผ ๋‚ด์šฉ์˜ ํ˜ผํ•ฉ๋œ ์ค„์— ๋Œ€ํ•ด ๋™์ผํ•œ ๋“ค์—ฌ์“ฐ๊ธฐ๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด):

<root_element>
  {%- if ... +%}
  <property>

  </property>
  {%- if ... +%}
 strips before

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„, ์šฐ๋ฆฌ๋Š” ์ œํ•œ๋œ ์ž์œ  ์‹œ๊ฐ„์„ ๊ฐ€์ง„ ์ž์› ๋ด‰์‚ฌ์ž๋กœ์„œ ์ด๊ฒƒ์„ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ปค๋ฎค๋‹ˆํ‹ฐ์— ์˜์กดํ•˜์—ฌ ๋ถ„์„์„ ์ œ๊ณตํ•˜๊ณ  ํŒจ์น˜๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์—†์„ ๋•Œ ์ฑ„์šฐ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋ฌธ์ œ์˜ ์˜ํ–ฅ์„ ๋ฐ›๊ณ  ์ˆ˜์ •์— ๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ PR์„ ์ œ์ถœํ•˜์‹ญ์‹œ์˜ค.

#749 ๊ด€๋ จ
#750 ๊ด€๋ จ

์—ฌ๊ธฐ์„œ ๋ฌธ์ œ๋Š” lstrip_blocks = False์ผ ๋•Œ "{%+ ๋ฌธ %}" ๊ตฌ๋ฌธ์ด "jinja2.exceptions.TemplateSyntaxError: ํƒœ๊ทธ ์ด๋ฆ„์ด ์˜ˆ์ƒ๋จ" ์˜ค๋ฅ˜ ๋ฉ”์‹œ์ง€์™€ ํ•จ๊ป˜ ์‹คํŒจํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ lstrip_blocks๊ฐ€ ์ด๋ฏธ ๋น„ํ™œ์„ฑํ™”๋œ ๊ฒฝ์šฐ ๋น„ํ™œ์„ฑํ™”ํ•  ๊ฒƒ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค์†Œ ์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘์ด์ง€๋งŒ ์กฐ๊ธˆ ๋” ์šฐ์•„ํ•˜๊ฒŒ ์‹คํŒจํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ์‹œ:

์ด๊ฒƒ์€ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค:

from jinja2 import Environment
env = Environment(lstrip_blocks=True, trim_blocks=False)
str7481 = '''
    <!-- 1 -->
    {%+ if True %}<!-- 2 -->
    foo<!-- 3 -->
    {% endif %}<!-- 4 -->
    <!-- 5 -->'''
str7482 = '''
    <!-- 1 -->
    {% if True %}<!-- 2 -->
    foo<!-- 3 -->
    {%+ endif %}<!-- 4 -->
    <!-- 5 -->'''
print(env.from_string(str7481).render())
print(env.from_string(str7482).render())

์ด๊ฒƒ์€ ๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

from jinja2 import Environment
env = Environment(lstrip_blocks=False, trim_blocks=False)
str7481 = '''
    <!-- 1 -->
    {%+ if True %}<!-- 2 -->
    foo<!-- 3 -->
    {% endif %}<!-- 4 -->
    <!-- 5 -->'''
str7482 = '''
    <!-- 1 -->
    {% if True %}<!-- 2 -->
    foo<!-- 3 -->
    {%+ endif %}<!-- 4 -->
    <!-- 5 -->'''
print(env.from_string(str7481).render())
print(env.from_string(str7482).render())

๋‚˜๋Š” ์ด ๋ฌธ์ œ๋ฅผ @davidism ๊ณผ ๋…ผ์˜ํ–ˆ๊ณ  ๊ทธ๋Š” ํ…œํ”Œ๋ฆฟ์˜ ๊ธฐ๋ณธ ๊ตฌ๋ฌธ์ด lstrip_blocks = False ๋•Œ ๋ณ€๊ฒฝ๋˜์–ด์„œ๋Š” ์•ˆ ๋œ๋‹ค๊ณ  ์ œ์•ˆํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‹ค์‹œ ๋งํ•ด์„œ, '{%+' ๋Š” ์ด ๊ฒฝ์šฐ์—๋„ ์—ฌ์ „ํžˆ ์œ ํšจํ•œ ๊ตฌ๋ฌธ์ด์–ด์•ผ ํ•˜์ง€๋งŒ ์˜๋ฏธ๋ก ์€ ์ค‘๋ณต๋˜๋ฏ€๋กœ '+' ๋ฌด์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด ์ž ์žฌ์ ์ธ ๋™์ž‘์„ ํ…Œ์ŠคํŠธํ•˜๊ณ  ๊ตฌํ˜„ํ•˜๋Š” PR์„ ์ œ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰