我正在用烧瓶和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安全包提供的宏。但我得到的只是错误:
UndefinedError: 'login_user_form' is undefined (after a long traceback)
我完全被困在这里了,在网站上读了大约一个小时的jinja2文档。我怎样才能使这份表格生效?
更新(很抱歉,更新太晚了):
My 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>
我的登录.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 %}
以一种抽象的方式,我想构建一个小部件,我可以导入并在另一个模板中使用,只实现一次这样的东西,比如登录表单。后来我想能够实现列表,它可以放在每个页面的siderbar中,而无需在每个页面上单独实现。我找到了Flask Plugable Views,但我还没有找到一个好的例子来理解正确的用法。
更新2:
这个(更新的)实现没有任何形式,没有任何错误。我想我可能误解了方块的用法。
**解决方案**
在Mark的帮助下,我发现模板上下文处理器作为变量的注入非常有用。对于一些人来说,这可能是显而易见的:flask安全性将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,使用内容块中的登录块,它就会工作。
您的错误是:
未定义错误:"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,则会出现错误。
如果您希望在应用程序的其他地方(例如在模板上下文处理器中)的模板上下文中定义login_user_form
,那么请确保应用程序的这一部分确实在工作。