美文网首页
Flask之五:模版与静态资源

Flask之五:模版与静态资源

作者: 奇奇乌布里 | 来源:发表于2020-04-25 00:51 被阅读0次

一、模版:存放位置、读取优先级

到处放,但根目录下的优先。

  • 模版文件夹 = 主py的模版文件夹 + 蓝图的模版文件夹
  • 主py的模版文件夹 = 主py同级的templates 文件夹
  • 蓝图的模版文件夹 = 蓝图py同级的某个文件夹, 其名由创建蓝图实例时的参数指定(也可以不指定,则 render_template()函数就不在这个蓝图下查找模版文件

  • 无论在主py还是在蓝图py响应函数里, 使用render_template() 函数返回模版时, Flask都会在所有模版文件夹中查找模版文件, 但是以主py的模版文件夹优先

模版文件夹(到处都有)

# 目录结构
├── bp_test
│   ├── static
│   └── templates  # 蓝图bp_test的模版文件夹,在创建蓝图时声明
│       └── my.html
├── bp_toto
│   ├── bp_2.py
│   ├── static
│   └── templates  # 蓝图bp_toto的模版文件夹,在创建蓝图时声明
│       └── my2.html
├── static
├── templates  # 主py的模版文件夹,有默认值不用声明
│   └── my.html
└── t.py


# 创建Flask时不需要指定模版文件夹名,因为有缺省值
app = Flask(__name__)

# 创建蓝图实例时需要指定模版文件夹名,因为没有缺省值
# 如果不设为templates,设为moban,也是作为模版文件夹适用"到处乱找"的
user_main = Blueprint("user_main", __name__,
    template_folder="templates")  # 设置模版文件名名
Flask的参数,模版文件夹名有默认值 蓝图的参数,模版文件夹没得默认值

返回渲染(render)后的模版

在响应函数中返回模版文件需要用到render_template()函数,这个函数使用前需要单独导入,具体来说:

from flask import Flask
from flask import render_template  # 渲染模版


app = Flask(__name__)

@app.route('/')
def root():
    return render_template('index.htm')  # 模版中的url_for()这些函数会被解析
  • 把模版放在蓝图下面,有利于蓝图模块的独立性(我比较推荐 ),但是容易导致模版文件重名的问题。建议蓝图的模版文件名前面加上蓝图名前缀,即可完美解决。

二、静态资源:引用

跟模版一样,也可以到处放;但是没有优先级问题。

  • 静态资源文件夹 = 主py静态资源文件夹 + 蓝图的静态资源文件夹
  • 主py的默认根目录static,蓝图的需要设置,一般是蓝图目录下的static
    以上两个与模版文件夹一致

  • 引用使用url_for()函数,第一个参数是静态资源文件夹的路径,第二个参数的资源的文件名(需要注明filename=''
  • 因为设置了路径,因此不存在重名、优先级的问题
# 创建蓝图时声明静态资源文件夹和模版文件夹
user_main = Blueprint("user_main", __name__,
    template_folder="templates",  # 设置模版文件夹
    static_folder="static")  # 设置静态资源文件夹

静态资源一般放置*.js*.cssimg 这些文件的,模版中使用url_for()函数指定资源位置(加载静态资源)。你如果硬要把html也放进static里去也行,但是就不能用url_for()函数指定静态资源位置了,在垮蓝图引用时会不方便)。

在模版中调用静态资源

由于数据表现还在在客户端用vue.js 来得实际,在后端就不要用太多的模版渲染折磨服务器CPU了。模版渲染就处理一下静态资源好了。

  • 第一个参数是静态资源文件夹名,如果资源在蓝图下面,还要加蓝图的endpoint前缀(就是创建蓝图实例时给的一个字符串参数
  • 第二个参数是注明关键字的参数:filename='',注明静态资源的文件名

需要特别说明的是:
即使是蓝图中的响应函数返回蓝图自己的模版文件夹中的模版文件,且文件里使用url_for()引用蓝图自己的静态资源,这个url_for()的第一个参数也要在static前面加模版的endpoint前缀!


很好理解啊,无论url_for()所在的文件在哪里,它引用资源时都要指定蓝图endpoint.static的路径

<!--css放最前面-->
<link rel="stylesheet" href="{{ url_for('static', filename='bootstrap.css') }}">

<!--body部分-->
<a href="{{ url_for('salut') }}">链接</a>  # 好处是路由可以随便改,不影响代码. 这里的参数是相应函数名(不带括号的)

<!--js放最后面-->
# 一般直接在根目录的static中加载
<script src="{{ url_for('static', filename='jquery.min.js') }}"></script>
# 如果要从蓝图的static中加载,需要加蓝图名前缀
<script src="{{ url_for('蓝图实例名.static', filename='vue.js') }}"></script>
<script src="{{ url_for('static', filename='bootstrap.js') }}"></script>

响应函数直接把html作为静态资源返回(不推荐)

还是可以把html直接放在static文件夹中,然后作为静态资源返回,此时需要调用app.send_static_file()方法,这个是app的方法,不需要额外导入。但需要注意的是:

  1. 不能用url_for()函数来引用静态资源
  2. 静态资源可以直接写路径引用,但是容易出错,特别是跨蓝图引用
  3. 如果js直接写CDN路径,就不会存在这方面的困扰了

具体来说:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def root():
    return app.send_static_file('index.htm')  # 返回static文件夹中的index.htm

总结一句

  • 静态资源 :因为要指定路径,因此没有优先级的问题
  • 模版文件 :在整个app的各种模版文件夹中乱找,有重名的话以主py所属的模版文件夹中的文件优先

三、url_for()跨蓝图引用生成超链接

  • 引用格式是:蓝图endpoint.响应函数名
  • 如果是主py下的响应函数就可以不加前面的蓝图endpoint.

具体是:

<a href="{{ url_for('蓝图endpoint.响应函数名') }}">链接指向蓝图下的一个路由</a>
<a href="{{ url_for('pombenbp2.root') }}">链接指向蓝图下的一个路由</a>
<a href="{{ url_for('root') }}">链接指向根目录</a>

详情可以在主py的代码中打印所有的endpoint到屏幕

print(app.url_map)  # app是Flask的实例

四、关于jinja2{{}}与vue.js{{}}的冲突

避免在vue.js中使用 {{}}引用变量

# 原来的
<p>{{ 变量名 }}</p>

# 改为
<p v-text='变量名'></p>

相关文章

网友评论

      本文标题:Flask之五:模版与静态资源

      本文链接:https://www.haomeiwen.com/subject/ntaaihtx.html