框架的本质
python提供的自定义web框架,其本质是基于socket
建立的服务端,与浏览器上的客户端,服务端基于请求做出响应,按http协议向客户端发送数据,浏览器访问IP和端口时自动与服务端进行连接,将请求信息发送给socket
服务端,如果手动实现该交互,需要每次访问建立间接,客户端发送请求,服务器端获取访问请求后,读取html文件再将其返回给客户端,其部分代码如下:
# 网络编程套接字建立通信后
send('b'HTTP/1.1 200 OK \r\n\r\n') # 客户端发送访问请求
f=open('html','rb') # 服务器端读取html
data=f.read()
conn.send(data) # 服务器端发送数据
也可以实现动态替换内容,也就是前端说的渲染,以字符串为例,使用data.replace(old,new)
即可实现字符串的新旧替换。
Flask框架
上述方法效率低,编写复杂,使用框架可以简略很多重复性的工作,比如建立间接和监听等步骤,最简单的示例代码如下:
# 该代码新建项目时自动生成 只是拿来作为介绍学习
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/') # 访问参数路径时自动触发函数内容,实现url与函数的映射
def hello_world(): # put application's code here
return 'hello'
#return render_template('hello.html') # 返回在template目录下的html
if __name__ == '__main__':
app.run() # pycharm限制不能加参数,如果加参数也不生效,要更改需要在系统配置中添加参数
执行后会控制台会输出如下字段:
此时点击连接会直接出现我们使用的return
字段,即出现hello
,报的错是涉及前后端服务器相关知识,暂时不必理会。
route装饰器
该装饰器实现了函数与路径的映射,可以通过对参数的调整来规定更详细的映射,比如/root/<id>
动态获取id
访问连接并执行不同的响应,其中id
的值可指定类型,否则默认为字符串,指定格式为<类型:变量名>
,简单示例代码如下:
@app.route('/<int:id>')
def hello_world(id): # put application's code here
return str(id) # 为什么要强制类型转换呢?
# 因为The return type must be a string, dict, list, tuple with headers or status,
# Response instance, or WSGI callable, but it was a int. 返回只能是字符串,字典,列表和元组
通过该方法就可以实现返回输入的访问连接。
有多个相同策略的参数时可以使用<any(访问路径):path>
输入访问路径在列举内时,会自动传给后面的path
变量,避免了多个输入重复写相同代码,基本和上面相同,不用示例介绍了就。
构造url
上面介绍的方法能实现url
到函数的映射,如果已知函数要找到url
又该如何操作呢?由此引入了url_for
函数,该函数第一个参数为函数名,其他参数作为查询参数添加到url
后,示例如下:
def findpath():
return url_for("hello_world",id=1) # 函数名要与已定义的方法相同
# 返回值为hello_world/1
使用该方法还是计算机中抽象代替具体的原则,函数中使用该方法填充,如果日后url
更改但函数名没更改,整个程序都照常运行,而且生成url
中的一些转义字符和编码等会自动帮我们完成。
末尾的斜杠/
如果访问时没加上,会被自动重定向到有/
的位置,但若访问原本没有斜杠的地址而加了斜杠,就会找不到404。
GET与POST方法
在请求过程中可能需要将信息传给后端,比如登录操作,示例代码如下:
@app.route('/login/')
def login():
return f'已登录{request.args.get('user')}'
此时使用/login?user=root
即可登录root
账户,但账号密码都在url
中以明文传输,互联网中裸奔是十分危险的,故介绍两种方法,get
和 post
方法。
GET - 从指定的资源请求数据,查询字符串是在 GET 请求的 URL 中发送的,使用?名称=值&名称=值
形式发送,如上面提到的方法。
POST - 向指定的资源提交要被处理的数据,查询字符串是在POST
请求的HTTP
消息主体中发送的,可以说psot
是一种加密的请求,敏感字段使用该方法传输为好。
装饰器可以传入一个关键字method
指定方法,默认为GET
,使用post
的装饰器方法如下:
@app.route('/login/',methods=['POST']) # 限定只支持post方法,否则报错
def login():
username = request.form['username']
password = request.form['password']
if username == 'admin' and password == '123456':
return 'Logged in successfully'
else:
return 'Invalid username or password'
这两个方法都可以通过request
库进行实现,调库即可实现。
页面跳转与重定向
具体又可分永久重定向和暂时重定向,分别返回状态301和302,两者都是实现域名重新跳转,永久重定向用于更换域名后,原有域名跳转到新域名,给用户适应熟悉的时间;暂时重定向用于登录等页面跳转,但状态不满足时,比如没登录但访问需登录的界面时会自动跳转至登录窗口。
登录状态由对比服务器端维护session
锁,和浏览器存储的cookie
是否匹配实现,如果匹配则登录,否则重定向跳转至登录界面,如session['username']='admin'
用于存储session
的值,具体判断过程距离如下:
if 'username' in session: # 登录代码
else : return redirect(url_for('login')) # 重定向至登录窗口
jinjia2模板
该模板为flask内置的默认模板,也可以换成django
等模板,该模板的特点是更自由,给用户实现的较少,限制也较少,而django
更像是半成品和确确实实的模板,用户只能做有限的更改,借助模板可以实现的功能如下:
渲染
html虽然是一种类似于markdown的标记语言,但我们日常使用的网页多数是可以动态变化和生成的,专业术语叫渲染,使用上面介绍过的render_template()
方法就可以实现,首先要在html中标记需要被替换的变量名,如{{user}}
,html中需要被数据替换的变量用{{}}
表示,后端的替换代码如下:
@app.route('/')
def index():
return render_template('test.html',user='kevin') # 将html响应与动态数据结合起来
使用该方法时,多个参数可以用字典传递。
控制语句
循环:
{% for 循环条件 %}
代码
{% endfor %}
判断:
{% if 判断条件 %}
代码
{% endif %}
过滤器
把当前的变量值传入过滤器,再根据自己的功能返回相应的值,相当于一个函数,如{{name|length}}
返回name的长度,还有first
返回序列第一个元素、upper
小写转大写等。
测试器
本质就是if
控制,加了个is
判断。
{% if 变量 is 测试内容%}
执行代码
{% endif %}
set方法
{% set name=' 变量名 '%}
,提前给变量赋值,无需后端传递
代码复用
宏
宏是类似于编程语言中函数的内容,定义如下:
{% macro 函数名(参数) %}
函数体
{% endmacro %}
宏可单独组成一个html文件,类似于包,给其他文件导入使用,导入命令为{% import '宏文件名' as 别名 %}
,通过{% 别名.函数名() %}
进行调用。
模板继承
{% extends '父模板名' %}
父类中写好框架,需要子类填充的部分使用{% block 块变量名称 %} {% endblock %}
代替,子类使用{% block 块变量名称 %} 填充内容 {% endblock %}
进行填充。
包含模板
html也可以使用编程语言中函数的思想进行复用,实现手段为示例如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>welcome</title>
</head>
<body>
{% include 'ahead.html' %} <!--引用ahead.html-->
<br>user: {{user}} <!--br换行-->
</body>
</html>
上面三种都是html中的代码复用,不同之处在于,宏是函数化,继承是挖坑给子类填充,包含是直接将另一个文件直接渲染出来。
总结
本章学习了python的flask框架,该框架基于socket
,用于搭建服务器/浏览器端结构,通过封装好的函数简化了很多原有操作,如建立连接和收发数据的过程,大大提升了开发效率,其jinjia2
模板是用于html动态渲染的工具,该模板对动态替换html中数据的过程进行了进一步封装,和其他模板相比,特点是限制更少,但做的也更少。