👏作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白
📕系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发
📧如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步👀
🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦
🍂博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人
🔥🔥🔥 python入门到实战专栏:从入门到实战
🔥🔥🔥 Python爬虫开发专栏:从入门到实战
🔥🔥🔥 Python办公自动化专栏:从入门到实战
🔥🔥🔥 Python数据分析专栏:从入门到实战
🔥🔥🔥 Python前后端开发专栏:从入门到实战
文章目录
模板继承
继承模板实战
add_url_rule与app.route
类视图
类视图的好处
类视图使用场景
基于调度方法的类视图
模板继承
为什么需要模版继承
模版继承可以把一些公用的代码单独抽取出来放到一个父模板中以后子模板直接继承就可以使用了。这样可以重复的利用代码,并且以后修改起来也比较方便
模版继承语法
使用 extends 语句,来指明继承的父模板。父模板的路径,也是相对于 templates 文件夹下的绝对路径
{% extends "base.html" %}
block语法
一般在父模版中,定义一些公共的代码。子模板可能要根据具体的需求实现不同的代码。
这时候父模版就应该有能力提供一个接口,让子模板来实现。从而实现具体业务需求的功能。
父模板
{% block block的名字 %}
{% endblock %}
子模板
{% block block的名字 %}
子模板中的代码
{% endblock %}
调用父模版代码block中的代码
默认情况下,子模板如果实现了父模版定义的block。那么子模板block中的代码就会覆盖掉父模板中的代码。如果想要在子模板中仍然保持父模板中的代码,那么可以使用 {{ super() }} 来实现
父模板
{% block block_body %}
<p style="background-color: blue">我是父模版block_body处的内容</p>
{% endblock %}
子模板
{% block block_body%}
{{ super() }}
<p style="background-color: green">我是子模版block_body处的内容</p>
{% endblock %}
调用另外一个block中的代码
如果想要在另外一个模版中使用其他模版中的代码。那么可以通过 {{ self.其他block名字() }} 就可以了
{% block title %}
txc首页
{% endblock %}
{% block block_body%}
{{ self.title() }}
<p style="background-color: green">我是子模版block_body处的内容</p>
{% endblock %}
注意
1. 子模板中的代码,第一行,应该是 extends
2. 子模板中,如果要实现自己的代码,应该放到block中。如果放到其他地方,那么就不会被渲染
继承模板实战
实现如下页面,需要使用
1、模板继承
2、引入静态资源
add_url_rule与app.route
add_url_rule
add_url_rule(rule,endpoint=None,view_func=None)
这个方法用来添加url与视图函数的映射。如果没有填写 endpoint ,那么默认会使用 view_func 的名字作为 endpoint 。以后在使用 url_for 的时候,就要看在映射的时候有没有传递 endpoint 参数,如果传递了,那么就应该使用 endpoint 指定的字符串,如果没有传递,那么就应该使用 view_func 的名字。
def my_list():
return "我是列表页"
app.add_url_rule('/list/',endpoint='sxt',view_func=my_list)
app.route原理剖析
这个装饰器底层,其实也是使用 add_url_rule 来实现url与视图函数映射的。
from flask import Flask,url_for
app = Flask(__name__)
@app.route('/',endpoint='index')
def index():
print(url_for('show'))
print(url_for('index'))
return "Hello"
def show_me():
return "这个介绍信息!!"
# endpoint 没有设置,url_for中就写函数的名字,如果设置了,就写endpoint的值
app.add_url_rule('/show_me',view_func=show_me,endpoint='show')
# @app.route 底层就是使用的 add_url_rule
if __name__ =='__main__':
app.run(debug=True)
类视图
之前我们接触的视图都是函数,所以一般简称函数视图。其实视图也可以基于类来实现,类视图的好处是支持继承,但是类视图不能跟函数视图一样,写完类视图还需要通过
app.add_url_rule(url_rule,view_func) 来进行注册
标准类视图使用步骤
1. 标准类视图,必须继承自 flask.views.View
2. 必须实现 dispatch_request 方法,以后请求过来后,都会执行这个方法。
这个方法的返回值就相当于是之前的视图函数一样。也必须返回 Response 或者子类的对象,或者是字符串,或者是元组。
3. 必须通过 app.add_url_rule(rule,endpoint,view_func) 来做url与视图的映射。 view_func 这个参数,需要使用类视图下的 as_view 类方法类转换:ListView.as_view('list') 。
4. 如果指定了 endpoint ,那么在使用 url_for 反转的时候就必须使用 endpoint 指定的那个值。如果没有指定 endpoint ,那么就可以使用 as_view(视图名字) 中指定的视图名字来作为反转。
from flask import Flask,url_for
from flask.views import View
app= Flask(__name__)
@app.route('/')
def index():
# print(url_for('mylist'))
print(url_for('my'))
return 'Hello'
class ListView(View):
def dispatch_request(self):
return '返回了一个List的内容!!'
#app.add_url_rule('/list',view_func=ListView.as_view('mylist'))
app.add_url_rule('/list',endpoint='my',view_func=ListView.as_view('mylist'))
# 用于测试
with app.test_request_context():
print(url_for('my'))
if __name__ =='__main__':
app.run(debug=True)
类视图的好处
1.可以继承,把一些共性的东西抽取出来放到父视图中,子视图直接拿来用就可以了。
2.但是也不是说所有的视图都要使用类视图,这个要根据情况而定。视图函数用得最多。
from flask import Flask,jsonify
from flask.views import View
app = Flask(__name__)
# 需求:返回的结果都必须是json数据
class BaseView(View):
def get_data(self):
raise NotImplementedError
def dispatch_request(self):
return jsonify(self.get_data())
class JsonView(BaseView):
def get_data(self):
return {'uname':'吕布','age':20}
class Json2View(BaseView):
def get_data(self):
return [
{'name':'艾派徳','lua':'Python'},
{'name':'程序员','lua':'Python'},
]
app.add_url_rule('/base',view_func=BaseView.as_view('base'))
app.add_url_rule('/json',view_func=JsonView.as_view('json'))
app.add_url_rule('/json2',view_func=Json2View.as_view('json2'))
if __name__ =='__main__':
app.run(debug=True)
类视图使用场景
from flask import Flask,render_template
from flask.views import View
app = Flask(__name__)
class BaseView(View):
def __init__(self):
self.msg = {
'main':'又更新了!!123'
}
class LoginView(BaseView):
def dispatch_request(self):
my_msg = '神奇的登录功能'
self.msg['my_msg'] = '神奇的登录功能'
# return render_template('login.html',msg= self.msg.get('main'),my_msg = my_msg)
return render_template('login.html',**self.msg)
class RegisterView(BaseView):
def dispatch_request(self):
self.msg['my_msg'] = '快捷的注册功能'
# return render_template('register.html',msg= self.msg.get('main'),my_msg = my_msg)
return render_template('register.html',**self.msg)
app.add_url_rule('/login',view_func=
LoginView.as_view('login'))
app.add_url_rule('/register',view_func=
RegisterView.as_view('register'))
if __name__ == '__main__':
app.run(debug=True)
基于调度方法的类视图
1. 基于方法的类视图,是根据请求的 method 来执行不同的方法的。如果用户是发送的 get 请求,那么将会执行这个类的 get 方法。
如果用户发送的是 post 请求,那么将会执行这个类的 post 方法。其他的method类似,比如 delete 、 put
2. 这种方式,可以让代码更加简洁。所有和 get 请求相关的代码都放在 get 方法中,所有和 post 请求相关的代码都放在 post 方法中。就不需要跟之前的函数一样,通过 request.method == 'GET'
案例
HTML
<form action="/login/" method="post">
<table>
<tr>
<td>账号:</td>
<td><input type="text" name="uname"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="pwd"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="立即登录"></td>
</tr>
<tr>
<td colspan="2">
{# <font color="red">{{ error }}</font>#}
{# 优化写法 :判断 #}
{% if error %}
<font color="red">{{ error }}</font>
{% endif %}
</td>
</tr>
</table>
</form>
python
#定义一个基于方法调度的 类视图
class LoginView(views.MethodView):
def get(self):
return render_template('login.html')
def post(self):
#模拟实现
#拿到前端页面传过来的 账号 和密码 去数据库做查询操作 查询到 (跳转主页面) ,反之跳转到login.html页面并给出错误提示信息
uname = request.form['uname']
pwd = request.form['pwd']
if uname=="aps" and pwd =="123":
return render_template('index.html')
else:
return render_template('login.html',error="用户名或者密码错误")
# 注册类视图
app.add_url_rule('/login/',
view_func=LoginView.as_view('my_login'))
改进1:
class LoginView(views.MethodView):
def get(self,error=None):
return render_template('login.html',error=error)
def post(self):
#模拟实现
#拿到前端页面传过来的 账号 和密码 去数据库做查询操作 查询到 (跳转主页面) ,反之跳转到
login.html页面并给出错误提示信息
uname = request.form['uname']
pwd = request.form['pwd']
if uname=="aps" and pwd =="123":
return render_template('index.html')
else:
return self.get(error="用户名或者密码错误")
# 注册类视图
app.add_url_rule('/login/',view_func=LoginView.as_view('my_login'))
改进2:
基于调度方法的类视图, 通常get()方法处理get请求,post()方法处理 post请求,
为了便于管理,不推荐post方法和get方法互相调用
class LoginView(views.MethodView):
def __jump(self,error=None):
return render_template('login.html', error=error)
def get(self, error=None):
return self.__jump()
def post(self):
# 模拟实现
#拿到前端页面传过来的 账号 和密码 去数据库做查询操作 查询到 (跳转主页面) ,反之跳转到
login.html页面并给出错误提示信息
uname = request.form['uname']
pwd = request.form['pwd']
if uname == "sxt" and pwd == "123":
return render_template('index.html')
else:
return self.__jump(error="用户名或者密码错误")
# 注册类视图
app.add_url_rule('/login/',view_func=LoginView.as_view('my_login'))