jinja2表单包含不起作用

时间:2013-12-16 18:47:44

标签: python html forms flask jinja2

我正在用烧瓶和jinja2做我的第一步。我已经完成了一些例子,但现在我尝试整合烧瓶安全性并且卡住了一点。

我尝试使用登录表单构建一个模态,所以我建立了一个这样的div:

<div class="modal">
<h3>Login</h3>
<form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
    {{ login_user_form.hidden_tag() }}
    {{ render_field_with_errors(login_user_form.email) }}
    {{ render_field_with_errors(login_user_form.password) }}
    {{ render_field_with_errors(login_user_form.remember) }}
    {{ render_field(login_user_form.next) }}
    {{ render_field(login_user_form.submit) }}
</form>

这是从flask-security提供的示例中获取的模板代码。现在我试着将其包装在

{% extends layout.html %}
{% block loginModal %} ... {% endblock %}

并尝试通过

在layout.html中调用它
{% block loginModal %}{% endblock %}

现在我学到的不是那种方式,因为内容被渲染并且仅调用了layout.html。

现在我试图通过include语句将该代码直接放在layout.html中,因为这不起作用我直接把它放进去。

我还添加了

{% from "security/_macros.html" import render_field_with_errors, render_field %}
第一行中的

,它们是flask-security包提供的宏。但我得到的只是错误:

UndefinedError: 'login_user_form' is undefined (after a long traceback)

我完全被困在这里,现在在网站上阅读jinja2文档大约一个小时。我怎样才能让这个表格起作用?

更新(对不起,这是一次延迟更新):

我的layout.html实现了所有页面的基本布局

<!doctype html>
<html>
<head>
  <title>MyExample</title>
  <link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/style.css') }}">
  <link rel=stylesheet type=text/css href="{{ url_for('static', filename='css/gumby.css') }}">
</head>
<body>
  <div class=page>
    <nav id="navbar-main-nav" class="navbar">
      <div class="row">
      <a class="toggle" gumby-trigger="#navbar-main-nav #main-nav" href="#"><i class="icon-menu"></i></a>
      <h1 class="four columns logo"><a href="/">Logo</a></h1>
      <nav class="five columns pull_right">
        <ul id="main-nav">
          <li><a href="/link1/"><span>Link1 </span></a></li>
          <li><a href="/link2/"><span>Link2</span><i class="icon-cog" title="Customize"></i></a></li>
    {% if current_user.is_authenticated() %}
    <li>Hello {{ current_user.name }}</li>
    <li><a href="{{ url_for('security.logout') }}">Logout</a></li>
    {% else %}
    <li><a href="#" class="switch" gumby-trigger="#modal1">Open Modal</a></li>
    <li><a href="{{ url_for('security.register') }}">Register</a></li>
    {% endif %}
    </ul>
  </nav>
    </div>
  </nav>

  <div class="modal" id="modal1">
    <div class="content">
      <a class="close switch" gumby-trigger="|#modal1"><i class="icon-cancel" /></i></a>
        <div class="row">
          <div class="ten columns centered">
            <div class="row">
              <div class="five columns">
                {% block loginModal %}{% endblock %}
              </div>
              <div class="five columns">
                 <!-- register Form -->
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

    {% block body %}{% endblock %}
  </div>
  <script src="{{ url_for('static', filename='js/libs/modernizr-2.6.2.min.js') }}"></script>
  <script src="{{ url_for('static', filename='js/libs/jquery-2.0.2.min.js') }}"></script>
  <script gumby-touch="js/libs/" src="{{ url_for('static', filename='js/libs/gumby.min.js') }}"></script>

</body>
</html>

我的login.html

{% extends layout.html %}
{% block loginModal %}
{% from "security/_macros.html" import render_field_with_errors, render_field %}
{% include "security/_messages.html" %}

   <h3>Login</h3>
   <form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
      {{ login_user_form.hidden_tag() }}
      {{ render_field_with_errors(login_user_form.email) }}
      {{ render_field_with_errors(login_user_form.password) }}
      {{ render_field_with_errors(login_user_form.remember) }}
      {{ render_field(login_user_form.next) }}
      {{ render_field(login_user_form.submit) }}
  </form>
{% endblock %}

我想以一种抽象的方式构建类似于小部件的东西,我可以导入并在另一个模板中使用,只能执行一次这样的事情,比如登录表单。后来我希望能够实现列表,这些列表可以放在每个页面的侧边栏中,而不需要在每个页面上单独实现。我发现Flask Plugable Views但我没有找到一个很好的例子来理解正确的用法。

更新2:

这个(更新的)实现根本不呈现任何形式,没有任何错误。我想我可能误解了块的使用。

**解决方案**

在Mark的帮助下,我发现模板上下文处理器作为一种变量注入非常有用。对于某些人来说可能很明显:flask-security将Forms作为导入提供,因此我的代码现在看起来像这样:

from flask.ext.security import LoginForm, RegisterForm
...
@app.context_processor
def inject_userForms():
    return dict(login_user_form=LoginForm(), register_user_form=RegisterForm() )

我将表单直接添加到我的layout.html中,现在效果很好。什么根本不起作用是包含块。如果我使用 blockception ,使用内容块中的登录块,它就可以工作。

1 个答案:

答案 0 :(得分:1)

您的错误是:

  

UndefinedError:'login_user_form'未定义

这来自模板,看起来像这样......

{% extends layout.html %}
{% block loginModal %}
{% from "security/_macros.html" import render_field_with_errors, render_field %}
{% include "security/_messages.html" %}

   <h3>Login</h3>
   <form action="{{ url_for_security('login') }}" method="POST" name="login_user_form">
      {{ login_user_form.hidden_tag() }}
      {{ render_field_with_errors(login_user_form.email) }}
      {{ render_field_with_errors(login_user_form.password) }}
      {{ render_field_with_errors(login_user_form.remember) }}
      {{ render_field(login_user_form.next) }}
      {{ render_field(login_user_form.submit) }}
  </form>
{% endblock %}

因此,您引用login_user_form,但Jinja2抱怨您实际上没有定义login_user_form。您通常在尝试调用函数来呈现模板时定义它。

def my_view():
    # ...
    return render_template('login.html', login_user_form=login_user_form)

如果你没有将'login_user_form'作为参数传递给render_template,你将收到错误。

如果您希望在应用程序的其他位置(例如template context processor)中的模板上下文中定义login_user_form,请确保应用程序的该部分确实正常工作。