Jinja2模板介绍和查找路径

在前面的章节中,视图只是直接返回文本,然而在实际生产环境中其实很少这样用,因为实际的页面大多带有样式和复杂逻辑的HTML代码,这可以让浏览器其渲染出非常漂亮的页面。

我们创建好flask项目,会发现有一个templates目录,这个目录就是用来存放模板文件

如果我们要使用模板,则需要导入render_template模块

我们先在templates目录下创建模板文件index.html,内容如下

 <h3>I love python</h3>

然后我们来渲染使用这个模板

...
from flask import render_template

@app.route('/')
def index():
    return render_template('index.html')

7、Flask实战第7天:Jinjia2模板

模板的路径是相对于templates的,如果这个模板路径是templates/posts/lists.html,那么路径应该这样写:

render_template('posts/lists.html')

我们可以看看为什么flask如何把templates作为模板路径的

按住ctrl,鼠标点击app = Flask(__name__)中的Flask,可以发现这个类默认有个参数template_folder='templates'

7、Flask实战第7天:Jinjia2模板

因此,如果我们不想把templates作为模板目录的话,比如用/home/heboan/haha这个目录,我们可以这样

app = Flask(__name__, template_folder='/home/heboan/haha')

 

模板传参及其技巧

视图函数如下,传入参数username

@app.route('/')
def index():
    return render_template('index.html', username='何波安')

模板文件index.html如下: 使用{{ 变量名 }}的方式引用

<body>

    姓名:{{ username }}

</body>

7、Flask实战第7天:Jinjia2模板

如果传入多个变量,可以这样写:

@app.route('/')
def index():
    return render_template('index.html', username='何波安', age=18, job='coder')

但是当参数很多的时候,这样就不方便了,我们可以用字典的方式来传参

@app.route('/')
def index():
    context = {
        'username': '何波安',
        'age': 18,
        'job': 'coder'
    }
    return render_template('index.html', context=context)

这样的话,我们模板就需要用context.username这种方式写

<body>

    姓名:{{ context.username }} <br />
    年龄:{{ context.age }} <br />
    工作:{{ context.job }}

</body>

7、Flask实战第7天:Jinjia2模板

如果我们想直接用username直接接收变量,我们可以这样做:把字典当成关键字参数

@app.route('/')
def index():
    context = {
        'username': '何波安',
        'age': 18,
        'job': 'coder'
    }
    return render_template('index.html', **context)

这样,我们就可以直接使用参数变量了

<body>

    姓名:{{ username }} <br />
    年龄:{{ age }} <br />
    工作:{{ job }}

</body>

如果参数的值也是字典

@app.route('/')
def index():
    context = {
        'username': '何波安',
        'age': 18,
        'job': 'coder',
        'attribute': {
            'height': '180cm',
            'weight': '80kg'
        }
    }
    return render_template('index.html', **context)

那么模板可以这样引用

<body>

    姓名:{{ username }} <br />
    年龄:{{ age }} <br />
    工作:{{ job }} <br />
    身高:{{ attribute.height }} <br />
    体重: {{ attribute.weight }}

</body>

7、Flask实战第7天:Jinjia2模板

 

模板中使用url_for

模板里面有很多超链接,比如

@app.route('/login/')
def login():
    return  render_template('login.html')

模板index.html

<a href="/login/">登录</a>

但是在实际开发中是不会写死的,这样不方便后期维护,这时候我们就可以用到url_for

<a href="{{ url_for('login') }}">登录</a>

如果需要传递参数,如

@app.route('/login/<user_id>')
def login(user_id):
    return  render_template('login.html')

模板index.html

<a href="{{ url_for('login', user_id='1') }}">登录</a>

 

过滤器

过滤器是通过管道符号"|"进行使用的,例如: {{ name| length }},将返回name的长度。过滤器相当于是一个函数,把当前的变量传入过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。

基本用法

@app.route('/')
def index():
    return render_template('index.html', position=-2)

index.html

position的绝对值是: {{ position|abs }}

7、Flask实战第7天:Jinjia2模板

default过滤器

{{ <变量名>|default('默认值', boolean=True)}}

场景: 当用户没有自定义个性签名的时候,使用default传递值,如下:

@app.route('/')
def index():
    context = {
        'signature': '世界真的好赞'
    }
    return render_template('index.html', **context)

index.html

个性签名: {{ signature|default('这个人真懒,什么都没有留下~') }}

个性签名字段signature存在,因此会显示"世界真的好赞"

7、Flask实战第7天:Jinjia2模板

当没有定义signature,则会显示"这个人真懒,什么都没有留下~"

@app.route('/')
def index():
    context = {
        #'signature': '世界真的好赞'
    }
    return render_template('index.html', **context)

7、Flask实战第7天:Jinjia2模板

当定义signature为None时,看看如何显示

@app.route('/')
def index():
    context = {
        'signature': None
    }
    return render_template('index.html', **context)

7、Flask实战第7天:Jinjia2模板

我们发现,显示的并不是default的值,而是None,这是为什么呢?

这是因为我们默认的default值只有变量不存在的时候才会引用,如果变量存在,那么就不会使用它

我们知道:None,空字符串,空字典,空列表等在布尔值都是False

如果我们想要在变量的布尔值是False的情况下就使用default的值,可以加上参数

个性签名: {{ signature|default('这个人真懒,什么都没有留下~', boolean=True) }}

还有一种简写方式

个性签名: {{ signature or '这个人真懒,什么都没有留下~' }}

 

escape字符转义

看如下例子

@app.route('/')
def index():
    context = {
        'signature': '<h1>世界真的好赞</h1>'
    }
    return render_template('index.html', **context)

index.html

个性签名: {{ signature }}

7、Flask实战第7天:Jinjia2模板

我们发现jinjia2自动把signature当做普通字符串处理了(为了安全性)

我们可以关闭自动处理,在{% autoescape off %}里面的内容是不会被jinjia2模板自动处理的

{% autoescape off %}
    个性签名: {{ signature }}
{% endautoescape %}

7、Flask实战第7天:Jinjia2模板

还有另外一种方法就是使用safe

个性签名: {{ signature| safe}}

7、Flask实战第7天:Jinjia2模板

在{% autoescape off %}里面的内容我们又想被转义处理,就可以使用escape了

{% autoescape  off%}
    个性签名: {{ signature| escape}}
{% endautoescape %}

7、Flask实战第7天:Jinjia2模板

last(value): 返回一个序列的最后一个元素。示例: names|last
lenth(value): 返回一个序列或者字典的长度。 示例:names|lenth
join(value, d=u''): 讲一个序列用d这个参数的值拼接成字符串
int(value): 将值转换为int类型
float(value): 将值转换为float类型
lower(value): 将字符串转换为小写
upper(value):将字符串转换为大写
replace(value, old, new): 替换将old替换为new的字符串
truncate(value,length=255, killwords=False): 截取length长度的字符串
trim: 截取字符串前后的空白字符
string(value): 将变量转换成字符串
wordcount(s): 计算一个长字符串中单词的个数
其他常用的过滤器

相关文章: