购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.1 模板的基本使用

4.1.1 渲染模板

在使用PyCharm Professional版创建完一个Flask项目后,默认会生成一个templates文件夹,如果没有修改模板查找路径,默认会在这个文件夹下寻找模板文件。模板文件可以是任意纯文本格式的文件,如TXT、HTML、XML等,但是为了让项目更规范,也为了与前端开发者更无缝地协作,一般都是用HTML文件来写模板代码。

注意

如果读者用的是非PyCharm Professional版创建的Flask项目,则可以手动创建templates文件夹。

首先在templates文件夹下创建index.html文件,然后输入以下代码。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>首页</title>
    </head>
    <body>
    <h1>这是首页</h1>
    </body>
    </html>

接下来在视图函数中使用render_template函数渲染index.html模板。在app.py中,将原来的hello_world视图函数修改为以下代码。

    from flask import Flask,render_template
    ...
    @app.route('/')
    def index():
        return render_template("index.xhtml")

render_template默认会从当前项目的templates文件夹下寻找index.html文件,读取后进行解析,再渲染成HTML代码返回给浏览器。在浏览器中访问http://127.0.0.1:5000,可以看到如图4-1所示的效果。

图4-1 首页渲染模板代码

从图4-1中可以看到,“这是首页”4个字已经是一级标题了,原因是模板中给“这是首页”4个字外面套了一个h1标签,至此我们就完成了一个最简单的模板渲染。

如果想修改模板文件的查找地址,可以在创建app时,给Flask类传递一个关键字参数template_folder指定具体路径,示例代码如下。

    app=Flask(__name__,template_folder=r"E:\flask_fullstack\demo04\
    mytemplates")

如此操作以后,Flask在寻找模板文件时,就不再从当前项目下的templates文件夹寻找了,而是从template_folder指定的路径寻找。项目在Debug模式开启的前提下再访问http://127.0.0.1:5000,会出现如图4-2所示的错误。

图4-2 模板没有找到

模板没有找到的原因是,在template_folder指定的文件夹下不存在一个叫作index.html的模板,如果想要解决此问题,只需要把templates文件夹下的index.html复制到template_folder指定的文件夹下即可。

4.1.2 渲染变量

HTML文件中的有些数据是需要动态地从数据库中加载的,不能直接在HTML中写死。一般的做法是,在视图函数中把数据先提取好,然后使用render_template渲染模板时传给模板,模板再读取并渲染出来。下面新建一个URL与视图函数映射,示例代码如下。

    @app.route("/variable")
    def variable():
        hobby = "游戏"
        return render_template("variable.xhtml",hobby=hobby)

以上代码中渲染了一个variable.html模板,这个模板文件的创建接下来会具体讲解。除模板名称外,还给render_template传递了一个hobby关键字参数,后续在模板中就可以使用这个变量了。

现在再在templates文件夹下创建一个variable.html模板文件(注意:要记得先删掉template_folder参数),然后输入以下代码。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>变量使用</title>
    </head>
    <body>
      <h1>我的兴趣爱好是:{{ hobby }}</h1>
    </body>
    </html>

从以上代码中可以看到,把变量放到两对花括号中即可使用变量。项目运行起来后,在浏览器中访问http://127.0.0.1:5000/variable,效果如图4-3所示。

图4-3 变量使用

图4-3中的文字“游戏”是从视图函数中通过render_template传过去的,并不是在HTML中写死的,所以变量的使用可以让同一个HTML模板渲染无数个不同的页面。

字典的键和对象的属性在模板中都可以通过点(.)的形式访问。在variable这个视图函数中添加两个新的变量,分别是字典类型的person,以及类对象类型的user。示例代码如下。

    class User:
        def __init__(self,username,email):
            self.username = username
            self.email = email
     
    @app.route("/variable")
    def variable():
        hobby = "游戏"
        person = {
            "name": "张三",
            "age": 18
        }
        user = User("李四","xx@qq.com")
        return
    render_template("variable.xhtml",hobby=hobby,person=person,user=user)

接下来,再在variable.html模板中通过点(.)的形式访问person的键和user属性。代码如下。

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>变量使用</title>
    </head>
    <body>
      <h1>我的兴趣爱好是:{{ hobby }}</h1>
      <p>person的姓名是:{{ person.name }},person的年龄是:{{ person.age }}</p>
      <p>user的用户名是:{{ user.name }},user的邮箱是:{{ user.email }}</p>
    </body>
    </html>

在浏览器中重新访问http://127.0.0.1:5000/variable,效果如图4-4所示。

字典键和对象的属性也都可以通过中括号的形式获取,如以下代码实际上是等价的。

    {{ user.name }}
    {{ user["name"] }}

读者可以自行修改variable.html中获取键和属性值的方式,最终效果是一样的。用点和中括号的形式访问,虽然效果一样,但是也存在以下不同。

图4-4 模板中通过点渲染字典和对象

(1)在模板中有一个变量的使用方式为foo.bar,那么在Jinja2中则按以下方式进行访问。

通过getattr(foo, 'bar')访问,先访问这个对象的属性。

如果没有找到,就通过foo.__getitem__("bar")方式访问,即访问这个对象的键。

如果以上两种方式都没有找到,返回一个undefined对象。

(2)在模板中有一个变量的使用方式为foo["bar"],那么在Jinja2中则按以下方式进行访问。

通过foo.__getitem__("bar")方式访问,即先访问这个对象的键。

如果没有找到,就通过getattr(foo, "bar")方式访问,即访问这个对象的属性。

如果以上都没找到,则返回一个undefined对象。

以上案例中,传递了3个变量到模板中,在变量比较多的情况,首先可以把所有的变量存放到字典中,然后在给render_template传递参数时使用**语法,将字典变成关键字参数,以上的variable视图函数代码可以改写为以下形式。

    @app.route("/variable")
    def variable():
        hobby = "游戏"
        person = {
            "name": "张三",
            "age": 18
        }
        user = User("李四","xx@qq.com")
        context = {
            "hobby": hobby,
            "person": person,
            "user": user
        }
        return render_template("variable.xhtml",**context)

以上代码的写法更加直观和简洁,在遇到需要传给模板的变量比较多的情况,都推荐使用这种方式。 rSx73sFYAnJEX/ulriJWmlUMMbLfM2jiQWWgcUpLjLBENzZUt1NHDrSUY+Vyo8aM

点击中间区域
呼出菜单
上一章
目录
下一章
×

打开