flask 无法加载样式_年薪百万之路--第七十三天 Flask框架(3)

本文介绍了Flask框架中模板继承的概念和使用方法,包括基本用法、进阶技巧以及注意事项。同时,讲解了如何在Flask项目中防范CSRF攻击,通过Flask-WTF扩展设置secret_key和使用CSRFProtect。此外,文章还探讨了数据库操作中的ORM概念及其优缺点,并提到了Flask-SQLAlchemy作为ORM的实现方式。

4d890a9d2546272a66e7f297784010d6.png

模板继承

在项目中,可能会遇到以下情况:

  • 多个模板具有完全相同的顶部和底部内容
  • 多个模板中具有相同的模板代码内容,但是内容中部分值不一样
  • 多个模板中具有完全相同的 html 代码块内容

像遇到这种情况,可以使用 JinJa2 模板中的 继承 来进行实现

模板继承是为了重用模板中的公共内容。一般Web开发中,继承主要使用在网站的顶部菜单、底部菜单版权信息,或弹出窗口。这些内容可以定义在父模板中,子模板直接继承,而不需要重复书写。

  • 标签定义的内容
{% block top %} {% endblock %}
  • 相当于在父模板中挖个坑,当子模板继承父模板时,可以进行填充。
  • 子模板使用 extends 指令声明这个模板继承自哪个模板
  • 父模板中定义的块在子模板中被重新定义,在子模板中调用父模板的内容可以使用super()

父模板代码:

base.html

{% block top %}
  顶部菜单
{% endblock top %}

{% block content %}
{% endblock content %}

{% block bottom %}
  底部
{% endblock bottom %}

子模板代码:

  • extends指令声明这个模板继承自哪
{% extends 'base.html' %}
{% block content %}
 需要填充的内容
{% endblock content %}

模板继承使用时注意点:

  1. 不支持多继承,一个子模板只能使用一次extends继承父模板
  2. 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
  3. 不能在一个模板文件中定义多个相同名字的block标签。重复则报错。
  4. 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。

模板继承进阶用法

模板继承还提供了同一模板相互调用的操作和在继承父级模板时继承父模板内容的操作

run.py代码:

from flask import Flask, render_template

# 初始化
app = Flask(import_name=__name__,template_folder='templates')

# 配置终端脚本运行项目
from flask_script import Manager
manager = Manager(app)

# 声明和加载配置
class Config():
    DEBUG = True
app.config.from_object(Config)

@app.route(rule='/')
def index():
    data={}
    return render_template("index3.html",**data)


if __name__ == '__main__':
    # 运行flask
    manager.run()

templates/base2.html,代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% block header %}
        <div>头部内容</div>
        {% block nav %}
        <div>导航菜单内容</div>
        {% endblock %}
    {% endblock %}

    {% block main %}
        <div>base里面编写的公共主体内容</div>
    {% endblock %}

    {% block footer %}
    <div>脚部内容</div>
        {# 调用当前模板中的其他block板块 #}
        {{ self.nav() }}
    {% endblock %}
</body>
</html>

templates/index3.html,代码:

{% extends "base2.html" %}

{% block main %}
    <div>index3.html编写的主体内容</div>
    {# 重写父模板内容时,如果希望继承原来父模板中的block模块,可以使用supper() #}
    {{ super() }}
{% endblock %}

include加载子模板

除了模板继承以外,在flask中还提供了include标签给我们进行模板分离使用的。

from flask import Flask, render_template

# 初始化
app = Flask(import_name=__name__,template_folder='templates')

# 配置终端脚本运行项目
from flask_script import Manager
manager = Manager(app)

# 声明和加载配置
class Config():
    DEBUG = True
app.config.from_object(Config)

@app.route(rule='/')
def index():
    data={}
    return render_template("index4.html",**data)


if __name__ == '__main__':
    # 运行flask
    manager.run()

templates/index4.html,代码:

{% include "header.html" %}
<div>index4.html的主体内容</div>
{% include "footer.html" %}

templates/header.html,代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <div>导航菜单</div>

templates/footer.html,代码:

<div>脚部内容</div>
</body>
</html>

模板宏

所谓的宏,就是模板中预先写好的一段类似函数的代码。这段代码名称叫[macro]。也就是宏。

在开发中经常出现一些html结构一样,但是样式属性可能不一样的代码部分,这时候可以预设一些模板宏,来进行复用模板代码。

模板宏需要通过{% macro 函数名(参数1,参数2….) %}{% endmacro %}进行声明。

run.py代码:

from flask import Flask, render_template

# 初始化
app = Flask(import_name=__name__,template_folder='templates')

# 配置终端脚本运行项目
from flask_script import Manager
manager = Manager(app)

# 声明和加载配置
class Config():
    DEBUG = True
app.config.from_object(Config)

@app.route(rule='/')
def index():
    data={}
    return render_template("index5.html",**data)


if __name__ == '__main__':
    # 运行flask
    manager.run()

templates/macro.html,代码:

{% macro func(text, name,type="text") %}
    <div>
    {{ text }}: <input type="{{ type }}" name="{{ name }}" />
    </div>
{% endmacro %}

templates/index5.html,代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {% import "macro.html" as macro %}
    {{ macro.func("用户名","username") }}
    {{ macro.func("密码","password","password") }}
</body>
</html>

在 Flask 项目中防范 CSRF 攻击

在 Flask 中, Flask-wtf 扩展有一套完善的 csrf 防护体系,对于我们开发者来说,使用起来非常简单

pip install flask_wtf
  1. 设置应用程序的 secret_key,用于加密生成的 csrf_token 的值
# 1. session加密的时候已经配置过了.如果没有在配置项中设置,则如下:
app.secret_key = "#此处可以写随机字符串#"

# 2. 也可以写在配置类中。
class Config(object):
    DEBUG = True
    SECRET_KEY = "dsad32DASSLD*13%^32"
    
"""加载配置"""
app.config.from_object(Config)

2.导入 flask_wtf.csrf 中的 CSRFProtect 类,进行初始化,并在初始化的时候关联 app

from flask.ext.wtf import CSRFProtect
CSRFProtect(app)

3.在表单中使用 CSRF 令牌:

<form method="post" action="/">
    <input type="hidden" name="csrf_token" value="{{ csrf_token() }}" />
</form>

run.py代码:

from flask import Flask, render_template,request

# 初始化
app = Flask(import_name=__name__,template_folder='templates')

# 配置终端脚本运行项目
from flask_script import Manager
manager = Manager(app)

# 声明和加载配置
class Config():
    DEBUG = True
    # 使用csrf防范机制,必须设置秘钥
    SECRET_KEY = "3fdsaf43ssa232"

app.config.from_object(Config)

# 注册csrf攻击防范模块到app应用中
from flask.ext.wtf import CSRFProtect
CSRFProtect(app)

@app.route(rule='/')
def index():
    data={}
    return render_template("index6.html",**data)

@app.route("/login",methods=["post"])
def login():
    print( request.form )
    return "ok"

if __name__ == '__main__':
    # 运行flask
    manager.run()

templates/index6.html,代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form action="/login" method="post">
        <input type="hidden" name="csrf_token" value="{{ csrf_token() }}">
        用户名:<input type="text" name="username"><br><br>
        密码:<input type="password"><br><br>
        <input type="submit" value="注册">
    </form>
</body>
</html>

数据库操作

ORM

ORM

ORM 全拼Object-Relation Mapping,中文意为 对象-关系映射。主要实现模型对象到关系数据库数据的映射

优点 :

  • 只需要面向对象编程, 不需要面向数据库编写代码.
    • 对数据库的操作都转化成对类属性和方法的操作.
    • 不用编写各种数据库的sql语句.
  • 实现了数据模型与数据库的解耦, 屏蔽了不同数据库操作上的差异.
    • 不再需要关注当前项目使用的是哪种数据库。

通过简单的配置就可以轻松更换数据库, 而不需要修改代码.

缺点 :

  • 相比较直接使用SQL语句操作数据库,有性能损失.
  • 根据对象的操作转换成SQL语句,根据查询的结果转化成对象, 在映射过程中有性能损失.

Flask-SQLAlchemy

flask默认提供模型操作,但是并没有提供ORM,所以一般开发的时候我们会采用flask-SQLAlchemy模块来实现ORM操作。

SQLAlchemy是一个关系型数据库框架,它提供了高层的 ORM 和底层的原生数据库的操作。flask-sqlalchemy 是一个简化了 SQLAlchemy 操作的flask扩展。

SQLAlchemy:

https://www.sqlalchemy.org/​www.sqlalchemy.org

安装 flask-sqlalchemy

pip install flask-sqlalchemy -i https://pypi.tuna.tsinghua.edu.cn/simple

如果连接的是 mysql 数据库,需要安装 mysqldb 驱动

pip install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple

安装flask-mysqldb时,注意

安装 flask-mysqldb的时候,python底层依赖于一个底层的模块 mysql-client模块
如果没有这个模块,则会报错如下:

Command "python setup.py egg_info" failed with error code 1 in /tmp/pip-install-21hysnd4/mysqlclient/

解决方案:

sudo apt-get install libmysqlclient-dev python3-dev

运行上面的安装命令如果再次报错如下:
   dpkg 被中断,您必须手工运行 ‘sudo dpkg --configure -a’ 解决此问题。

则根据提示执行命令以下命令,再次安装mysqlclient
	sudo dpkg --configure -a
	apt-get install libmysqlclient-dev python3-dev

解决了mysqlclient问题以后,重新安装 flask-mysqldb即可。
pip install flask-mysqldb -i https://pypi.tuna.tsinghua.edu.cn/simple
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值