flask(二)http协议之request和response

1.请求报文和响应报文
打开浏览器,当输入一个url,点击访问的时候会向目标服务器发送一个HTTP请求,请求的会经过os七层,可以理解为通过url请求目标服务器的一段具体的资源,这种浏览器与服务器之间交互的数据被称为报文。

应用层:网络服务与最终用户的一个接口。协议有:HTTP FTP TFTP SMTP SNMP DNS TELNET HTTPS POP3 DHCP
表示层:数据的表示、安全、压缩。格式有:JPEG、ASCll、EBCDIC、加密格式等
会话层:建立、管理、终止会话。对应主机进程,指本地主机与远程主机正在进行的会话
传输层:定义传输数据的协议端口号,以及流控和差错校验。协议有:TCP UDP,数据包一旦离开网卡即进入网络传输层
网络层:进行逻辑地址寻址,实现不同网络之间的路径选择。协议有:ICMP IGMP IP(IPV4 IPV6)
数据链路层:建立逻辑连接、进行硬件地址寻址、差错校验等功能。将比特组合成字节进而组合成帧,用MAC地址访问介质,错误发现但不能纠正。
物理层:建立、维护、断开物理连接。

请求报文:请求时浏览器发送的数据称为请求报文
响应报文:服务器收到了请求后返回给浏览器的数据称为响应报文

这里是BS架构去讲解, BS架构就是浏览器和后端服务器的交互,CS架构是客户端和服务端的交互,BS架构可以理解为CS架构的一个具体实现。浏览器就是客户端,后端服务器就是服务端。

2.报文中的GET请求和POST请求
GET提交的数据会放在URL之后,以?分割URL和传输数据,参数之间以&相连。
POST方法是把提交的数据放在HTTP包的请求体中。
GET提交的数据大小有限制(因为浏览器对URL的长度有限制)
POST方法提交的数据无限制
GET与POST请求在服务端获取请求数据方式不同。

3.response对象
三种用make_response传响应头的方法

@app.route("/page_two")
def page_two():
    response = make_response('page_two page', 200)
    response.headers["name"] = "page_four" # 添加响应头
    return response

@app.route("/page_three")
def page_three():
    response = make_response('page_three page')
    return response, 200, {"name": "page_three"}

@app.route("/page_four")
def page_four():
    response = make_response('page_four page', 200, {"name": "page four"})
    return response

return Response对象

@app.route("/page_five")
def page_five():
    response = Response("page five")
    response.status_code = 299 # Status Code: 299 notknown
    response.status = "298 notok" # 设置Status Code: 298 notok
    return response, "297 okok", {"name": "page fiv"} # Status Code: 297 okok

视图函数可以返回一个元组(多个值),返回多个值的话,必须注意顺序,第一位必须为字符串或者Response对象,第二个参数应该为状态码,第三个参数就是请求头里的数据了

属性

headers : 设置请求头信息
status : String类型的数据,格式为这种:"200 ok"
status_code : int 类型,就是状态码,但是不能是自定义的状态码
data : 需要返回到前端的数据
content_type:数据类型
@app.route("/page_five")
def page_five():
    response = Response("<h1>page five</h1>") # 返回response对象
    print(response.content_type) # text/html; charset=utf-8
    print(response.headers) # Content-Type: text/html; charset=utf-8 Content-Length: 18
    print(response.status) # 200 OK
    print(response.status_code) # 200
    response.set_cookie('name','zz') # 设置cookie
    return response

4.request对象
request对象封装解析了请求报文中的数据,其大部分功能是由依赖包werkzeug完成的,并且每个request对象都是线程隔离的,保证了数据的安全性。

request对象解决了很多问题,各种请求的方法以及请求参数的格式都不一致,所以flask做了一个request对象,专门去解析各种方法以及各种格式的请求,以便于去开发使用。

request对象使用需要从flask模块中导入

from flask import Flask, request

使用request属性获取url 访问:http://127.0.0.1:5000/student_list/?name=zz

@app.route('/student_list/')
def student_list():
    print(request.path)          # 输出 /student_list/
    print(request.full_path)     # 输出 /student_list/?name=zz
    print(request.host)          # 输出 127.0.0.1:5000
    print(request.host_url)      # 输出 http://127.0.0.1:5000/
    print(request.base_url)      # 输出 http://127.0.0.1:5000/student_list/
    print(request.url)           # 输出 http://127.0.0.1:5000/student_list/?name=zz
    print(request.url_root)      # 输出 http://127.0.0.1:5000/
    print(request.headers)       # 输出请求头
    return 'request.url测试'

5.GET请求
GET请求一般用于在服务器上获取资源,不会更改服务器的状态。结合request对象,使用request.args属性获取get传来的参数

@app.route('/student_name/', methods=['GET']) # 指定浏览器只能以GET方法访问服务端
def school_name_list():
    name = request.args.get('name')
    age = request.args.get('age')
    return "学生的姓名为{},年龄为{}".format(name, age) # 学生的姓名为‘zz’,年龄为14
# http://127.0.0.1:5000/student_name/?name='zz'&age=14

6.POST请求
会给服务器提交一些数据或者文件,会对服务器的状态产生影响。render_template的简单使用from flask import render_template
app.py

from flask import Flask, request, render_template, json
import settings
import uuid
app = Flask(__name__)
app.config.from_object(settings) # 配置文件解耦
users = list()

@app.route('/')
def index():
    uid = uuid.uuid4() # 生成uuid
    print(uid)
    # r = render_template('index.html')
    # return r
    return render_template('index.html')
    
# 如果没有设置methods,则默认为GET
@app.route('/register',methods=['GET','POST'])
def register():
    print(request.method)
    if request.method=='POST':
        # 取form表单提取的信息request.form.get()
        username = request.form.get('username')
        password = request.form.get('password')
        repassword = request.form.get('repassword')
        # 密码一致性校验
        if password == repassword:
            # 保存用户
            user = {'username':username,'password':password}
            users.append(user)
            return '注册成功!'
            # return '注册成功!<a href = "/">返回首页</a>' # 点击后返回首页
        else:
            return '两次密码不一致'
    return render_template('register.html') # 渲染模板文件 默认去模板文件夹中找文件

@app.route('/show')
def show():
    j_str = json.dumps(users) # 将列表转化为json字符串
    return j_str

if __name__ ==  "__main__":
    print(app.url_map) # 路由规则表
    app.run()

index

<head>
    <meta charset="UTF-8">
    <title>首页</title>
</head>
<body>
{# a*3加tab键快速创建 #}
<a href="/register">注册</a>
<a href="">登录</a>
<a href="/show">展示</a>
</body>

register

<head>
    <meta charset="UTF-8">
    <title>用户注册界面</title>
</head>
<body>
<h1>用户注册</h1>
{# form>p*4>input加tab键 #}
{# 如果method为GET,则action不能为本路径 #}
{# form标签的action指定的是跳转的页面。并且会自动拼接成http://127.0.0.1:5000/register #}
<form action="/register" method="POST">
    {# 后端通过name拿取数据 #}
    <p><input type="text" name="username" placeholder="用户名"></p>
    <p><input type="password" name="password" placeholder="密码"></p>
    <p><input type="password" name="repassword" placeholder="确认密码"></p>
    <p><input type="submit" value="注册"></p>
</form>
</body>

7.重定向

客户端浏览器中输入/register–后端根据路由规则表自上而下找到匹配的函数执行函数,最后render_template(’’)的时候使用模板引擎,转换成字符串形式–通过视图函数的return返回字符串给客户端浏览器
浏览器看到表单并填写,使用post方式返回给服务器端,服务器端获取提交数据,成功后redirect发送code=302以及location=/给浏览器
浏览器收到302后寻找location并将url栏地址替换为http://127.0.0.1:5000+location再次向服务器端请求,服务器端找到首页内容返回

# 替换上文app.py文件中的register
# 密码一致性校验
        if password == repassword:
            # 保存用户
            user = {'username':username,'password':password}
            users.append(user)
            return redirect('/') # 有两次相应:1.302+location 2.返回location请求地址内容

重定向+url_for

return redirect(url_for('index'))

8.装饰器
①函数加装饰器
装饰器一定要写在注册路由的下面,写在视图函数的上面。
装饰器内部最好要使用@wraps(func)方法,用于保护被装饰函数的属性。

def login_verify(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        user_name = request.args.get('user')
        password = request.args.get('password')
        if user_name == 'zz' and password == '123':
            return func(*args,**kwargs)
        else:
            return '请登录'
    return wrapper

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/my_info/')
@login_verify # 先进行验证 成功后返回个人信息页面,否则返回请登录
# http://127.0.0.1:5000/my_info/?user=zz&password=123
def my_info():
    return '个人信息页面'

②类加装饰器

from flask import Flask, views, request, url_for
from functools import wraps
import settings

app = Flask(__name__)
app.config.from_object(settings) # 配置文件解耦

def login_verify(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        user_name = request.args.get('user')
        password = request.args.get('password')
        if user_name == 'zz' and password == '123':
            return func(*args,**kwargs)
        else:
            return '请登录'
    return wrapper

class Test(views.MethodView):
    methods = ['GET','POST']  # 指定可以接收的方法
    decorators = [login_verify,]  # 指定自定义的装饰器
    def get(self):
        print(url_for('test_s')) # endpoint='test_s' # /test
        return 'get'
    def post(self):
        return 'post'
app.add_url_rule('/test',view_func=Test.as_view(name='testa'),endpoint='test_s')
# Test.as_view(name='函数名')会返回一个函数,name是为这个函数命的名字,可以通过这个函数进行分发请求等操作。
# Converts the class into an actual view function that can be used with the routing system
# http://127.0.0.1:5000/test/?user=zz&password=123

视图函数的返回值
response响应:
str >>> 自动转成response对象
dict >>> 转为json格式
response >>> response对象
make_response >>> response对象
redirect >>> 重定向 302状态码
render_template >>> 模板渲染

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值