Jinja2 设置块在 Django 中无法识别

Posted

技术标签:

【中文标题】Jinja2 设置块在 Django 中无法识别【英文标题】:Jinja2 set block not recognized in Django 【发布时间】:2020-06-18 20:09:53 【问题描述】:

我在发布之前搜索了 2 天,所以我真的希望它不是重复的问题。

我正在构建我的第一个 Django 站点,进入它后我意识到我宁愿拥有 jinja2 的力量。我将 jinja2 安装到我的虚拟环境中并对 django 进行了必要的更改(见下文)。但是,django 似乎使用标准 django 模板引擎而不是 jinja2 呈现模板。

使用 % block content % 模板内容 % endblock content % 时,我的所有代码都按预期工作

我尝试使用 % set % 模板内容 % endset % 而不是块,以便我可以在 base.html 中复制模板。但我收到此错误:

django.template.exceptions.TemplateSyntaxError: Invalid block tag on line 7: 'set'. Did you forget to register or load this tag?
[05/Mar/2020 22:27:37] "GET /bge/ HTTP/1.1" 500 161659

我对我的项目进行了以下更改以尝试使 jinja2 工作:

设置:

TEMPLATES = [
    
        'BACKEND': 'django.template.backends.jinja2.Jinja2'
        ,
        'DIRS': [os.path.join(BASE_DIR, 'templates/jinja2')],
        'APP_DIRS': True,
        'OPTIONS': 
            'environment': 'bge_app.jinja2.environment'
        ,
    ,
    
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [(os.path.join(BASE_DIR, 'templates')),],
        'APP_DIRS': True,
        'OPTIONS': 
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        ,
    ,
]

jinja2.py 添加到 django_projects\bge\bge_app

from django.contrib.staticfiles.storage import staticfiles_storage
from django.urls import reverse
from jinja2 import Environment


def environment(**options):
    env = Environment(**options)
    env.globals.update(
        'static': staticfiles_storage.url,
        'url': reverse,
    )
    return env

这是 django_projects\bge\bge_app\templates\jinja2\dice.html 中的模板

% extends "base.html" %
% load static %
% block title %
<Title>Dice</Title>
% endblock title %

% set dice_content %
    <br/>
<div class="container">
    <div class="row">
        <form class="m-3" method="POST">
            % csrf_token %
            <div class="input-group">
              <div class="input-group-prepend">
                <button type="submit" class="btn btn-info">Add Die</button>
                 die_size_form.num_sides 
                 die_size_form.active 
              </div>
            </div>
        </form>
        <a href="% url 'roll_dice' %">
        <button type="button" class="btn btn-info m-3">Roll Dice</button>
        </a>
        <table class="m-2 table-bordered text-center">
            <tr>
            <th class="p-2">Roll Sum</th>
            </tr>
            <tr>
                <td>
                     active_dice_sum 
                </td>
            </tr>
        </table>
    </div>
        <table class="table-hover table-bordered text-center table-sm col-md-10">
            <tr>
                <th> Die Sides</th>
                <th> Die Status</th>
                <th> Roll Value</th>
                <th> Remove Die</th>
            </tr>
            % for die in all_dice %
                % if die.active %
                    % if die.num_sides == 6 %
                        <tr>
                            <td>D6 &nbsp;<img src="% static '/images/dice/d6.png' %" ></td>
                            <td><a href="% url 'deactivate_die' die.id %">
                                <button type="button" class="btn btn-success">Active</button>
                                </a>
                            </td>
                            <td>  die.roll_value  </td>
                            <td><a href="% url 'remove_die' die.id %">
                            <button type="button" class="btn btn-danger">X</button>
                            </a>
                            </td>
                        </tr>
                    % else %
                        <tr>
                            <td>D  die.num_sides </td>
                            <td><a href="% url 'deactivate_die' die.id %">
                                <button type="button" class="btn btn-success">Active</button>
                                </a>
                            </td>
                            <td>  die.roll_value  </td>
                            <td><a href="% url 'remove_die' die.id %">
                                <button type="button" class="btn btn-danger">X</button>
                                </a>
                            </td>
                        </tr>
                    % endif %
                % else %
                    <tr>
                        <td>D  die.num_sides </td>
                        <td><a href="% url 'activate_die' die.id %">
                            <button type="button" class="btn btn-secondary">Inactive</button>
                            </a>
                        <td>  die.roll_value  </td>
                         <td><a href="% url 'remove_die' die.id %">
                        <button type="button" class="btn btn-danger">X</button>
                        </a>
                        </td>
                    </tr>
                % endif %
            % endfor %
        </table>
% endset dice_content %
</div>

这是base.html

% load static %
<!doctype html>
<html lang="en">
  <head>
    <!-- Required meta tags -->
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

    <!-- Bootstrap CSS -->
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">

  <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
  <a class="navbar-brand" href="% url 'index' %"><i>Board Game Essentials</i></a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNav">
    <ul class="navbar-nav">
      <li class="nav-item active">
        <a class="nav-link" href="% url 'player_setup' %">Player Setup</a>
      </li>
      <li class="nav-item active">
        <a class="nav-link" href="% url 'die_pool' %">Dice</a>
      </li>
      <li class="nav-item active">
        <a class="nav-link" href="% url 'hp_tracker' %">HP Tracker</a>
      </li>
      <li class="nav-item active">
        <a class="nav-link" href="% url 'score_calc' %">Score Calculator</a>
      </li>
    </ul>
  </div>
</nav>

#want to call set multiple times here#

    <!-- Optional javascript -->
    <!-- jQuery first, then Popper.js, then Bootstrap JS -->
    <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
  </body>
</html>

【问题讨论】:

你能显示 base.html 吗? % set dice_content % 中的“设置”是什么? 我在我的问题中添加了 base.html。我想将 dice.html 中的所有内容放在一个集合块 set dice_content dice.html 的东西 endset dicecontent 中,然后在 base.html 中调用它。我可能使用 set 错误,但实际上我更担心 django 无法识别 set 标签,因为这意味着 jinja2 无法正常工作。 您没有在 base.html 中定义任何块。我认为您希望 【参考方案1】:

base.html(一些变化)

 <!doctype html>
    % load static %
    <html lang="en">
      <head>
        <!-- Required meta tags -->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>% block title % % endblock %</title>
        <!-- Bootstrap CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
    </head>
<body>
      <nav class="navbar navbar-expand-lg navbar-dark bg-primary">
      <a class="navbar-brand" href="% url 'index' %"><i>Board Game Essentials</i></a>
      <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
        <span class="navbar-toggler-icon"></span>
      </button>
      <div class="collapse navbar-collapse" id="navbarNav">
        <ul class="navbar-nav">
          <li class="nav-item active">
            <a class="nav-link" href="% url 'player_setup' %">Player Setup</a>
          </li>
          <li class="nav-item active">
            <a class="nav-link" href="% url 'die_pool' %">Dice</a>
          </li>
          <li class="nav-item active">
            <a class="nav-link" href="% url 'hp_tracker' %">HP Tracker</a>
          </li>
          <li class="nav-item active">
            <a class="nav-link" href="% url 'score_calc' %">Score Calculator</a>
          </li>
        </ul>
      </div>
    </nav>

    #want to call set multiple times here#
    % block set %


% endblock %
        <!-- Optional JavaScript -->
        <!-- jQuery first, then Popper.js, then Bootstrap JS -->
        <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
      </body>
    </html>

您的模板

% extends "base.html" %
% block title %Your webpage title % endblock %
% block set %
<div class="container">
    <div class="row">
        <form class="m-3" method="POST">
            % csrf_token %
            <div class="input-group">
              <div class="input-group-prepend">
                <button type="submit" class="btn btn-info">Add Die</button>
                 die_size_form.num_sides 
                 die_size_form.active 
              </div>
            </div>
        </form>
        <a href="% url 'roll_dice' %">
        <button type="button" class="btn btn-info m-3">Roll Dice</button>
        </a>
        <table class="m-2 table-bordered text-center">
            <tr>
            <th class="p-2">Roll Sum</th>
            </tr>
            <tr>
                <td>
                     active_dice_sum 
                </td>
            </tr>
        </table>
    </div>
        <table class="table-hover table-bordered text-center table-sm col-md-10">
            <tr>
                <th> Die Sides</th>
                <th> Die Status</th>
                <th> Roll Value</th>
                <th> Remove Die</th>
            </tr>
            % for die in all_dice %
                % if die.active %
                    % if die.num_sides == 6 %
                        <tr>
                            <td>D6 &nbsp;<img src="% static '/images/dice/d6.png' %" ></td>
                            <td><a href="% url 'deactivate_die' die.id %">
                                <button type="button" class="btn btn-success">Active</button>
                                </a>
                            </td>
                            <td>  die.roll_value  </td>
                            <td><a href="% url 'remove_die' die.id %">
                            <button type="button" class="btn btn-danger">X</button>
                            </a>
                            </td>
                        </tr>
                    % else %
                        <tr>
                            <td>D  die.num_sides </td>
                            <td><a href="% url 'deactivate_die' die.id %">
                                <button type="button" class="btn btn-success">Active</button>
                                </a>
                            </td>
                            <td>  die.roll_value  </td>
                            <td><a href="% url 'remove_die' die.id %">
                                <button type="button" class="btn btn-danger">X</button>
                                </a>
                            </td>
                        </tr>
                    % endif %
                % else %
                    <tr>
                        <td>D  die.num_sides </td>
                        <td><a href="% url 'activate_die' die.id %">
                            <button type="button" class="btn btn-secondary">Inactive</button>
                            </a>
                        <td>  die.roll_value  </td>
                         <td><a href="% url 'remove_die' die.id %">
                        <button type="button" class="btn btn-danger">X</button>
                        </a>
                        </td>
                    </tr>
                % endif %
            % endfor %
        </table>
</div>

 % endblock %

您在基本模板% block your_block_name %% endblock %中定义块并在子模板中使用这些块。如果您有任何错误或不理解答案,请告诉我。此外,您不必安装任何东西(如 jinja2)。 Django 已经支持此功能。

【讨论】:

非常感谢您抽出宝贵时间调查我的问题。我知道 blockendblock 是如何工作的,并且在我的问题中我说我的代码在使用块时确实可以工作。但是,您不能在 base.html 中多次调用同一个块,这是我想要做的。所以为此我需要使用宏或设置,这就是我想使用 jinja2 的原因。稍后我还想要一些其他的 jinja2 功能,但现在我真的很想看到 jinja2 在 django 中被识别。我一定遗漏了一些明显的东西,但我只是没有看到。

以上是关于Jinja2 设置块在 Django 中无法识别的主要内容,如果未能解决你的问题,请参考以下文章

使用 jinja2 作为 django 模板引擎时出错:无法导入名称“环境”

使用 jinja2 模板引擎渲染 django 表单

Django OAuth 2 客户端设置 - 客户端无法识别令牌

Django 无法识别 DEBUG = False

获取与 django 1.x 集成的 jinja2 模板的翻译字符串?

如何在 Django 1.8 中使用 jinja2 作为模板引擎