【5.0】Flask框架之请求与响应

【一】引入

  • 所有web:请求对象,响应对象(go,java,ptyhon)

【二】flask请求对象

  • django:request(每个请求一个request),新手四件套
  • flask:requset:全局的,但是也是每个请求一个request,新手三件套
from flask import Flask, render_template, request
from flask.views import View, MethodView

app = Flask(__name__, template_folder='templates')


@app.route('/', methods=['GET', 'POST'])
def index():
    # 在哪个视图函数执行 , request对象就是属于哪个视图函数
    print(request.path)  # /
    return 'index'


@app.route('/home', methods=['GET', 'POST'])
def home():
    print(request.path)  # /home
    return 'home'


if __name__ == '__main__':
    app.run()
  • 参数

    # request.method  		提交的方法
    # request.args 			get请求提及的数据
    # request.form   		post请求提交的数据
    # request.values  		post和get提交的数据总和
    # request.cookies  		客户端所带的cookie
    # request.headers  		请求头
    # request.path     		不带域名,请求路径
    # request.full_path  	不带域名,带参数的请求路径
    # request.script_root  
    # request.url           带域名带参数的请求路径
    # request.base_url		带域名请求路径
    # request.url_root      域名
    # request.host_url		域名
    # request.host			127.0.0.1:500
    # request.files
    # obj = request.files['the_file_name']
    # obj.save('/var/www/uploads/' + secure_filename(f.filename))
    

【二】flask响应对象

【1】四件套:

  • 1 直接返回字符串
  • 2 返回模板:render_template
  • 3 返回重定向:redirect,
  • 4返回json格式:jsonify

【2】响应中写cookie

res = make_response('home') 
res.set_cookie('yyy', 'yyy', path='/home')
# 删除cookie
# res.delete_cookie('key')

【3】响应头中写内容

res = make_response('home')  # res 就是响应对象
res.headers['xxx'] = 'xxx'
  • 参数
# request.method  		请求的方法
# request.args  		get请求提交的数据
# request.form   		post请求提交的数据
# request.values 		post和get提交的数据总和
# request.cookies  		客户端所带的cookie
# request.headers  		请求头
# request.path     		不带域名,请求路径
# request.full_path  	不带域名,带参数的请求路径
# request.url           带域名带参数的请求路径
# request.base_url		带域名请求路径
# request.url_root      域名
# request.host_url		域名
# request.host			服务端地址
# request.files
# obj = request.files['the_file_name']
# obj.save('/var/www/uploads/' + secure_filename(f.filename))

【三】模版

  • dtl中学的所有知识,拿到这,都可以用---》dtl是django自己的,不能使用

    • dtl指的是Django模板语言(Django Template Language)。
    • 它是Django框架内置的模板语言,用于在网页中嵌入动态内容。
    • 这句话的意思是,之前在其他地方学到的使用dtl的知识,在此处无法使用。
    • 因为dtl是针对Django框架设计的,不能在其他环境中直接使用。
  • jinja2 模板语法,第三方,flask使用了它,它可以单独使用

    • jinja2是一个独立的第三方模板引擎,常被用于Python web框架中,其中包括Flask框架。
    • 与dtl相比,jinja2是一个可以单独使用的模板引擎,不依赖于特定的框架。
    • 因此,除了在Flask中使用外,也可以在其他Python项目中使用jinja2。
  • jinja2 模板语法 支持括号调用,支持字典[]取值----》模板中写原来python的语法都支持

    • jinja2模板语法支持使用括号进行函数/方法的调用以及使用方括号获取字典的值。
    • 这意味着,在jinja2模板中可以使用类似于Python的语法来进行相应的操作,方便开发人员转换和编写模板代码。
  • jinja2模板语法处理了xss攻击

    • xss攻击(跨站脚本攻击)是一种网络安全漏洞,攻击者通过在网页中注入恶意脚本,从而对用户数据和个人隐私造成危害。
    • jinja2模板引擎通过在渲染模板时对特殊字符进行转义处理,防止注入恶意脚本。
    • 具体来说,jinja2会将字符串中的一些特殊字符(如尖括号<和>)替换为相应的HTML实体编码,以确保这些字符不被解释为HTML标签或脚本。
  • extends, include

    • extends和include是jinja2模板语法中常用的两个指令。
    • extends指令允许在一个模板中继承另一个模板的内容,可以实现模板的重用和模块化开发。
    • include指令用于包含其他模板文件的内容,可以在一个模板中引用其他模板的部分内容,实现模板的组合使用。
  • 1.Markup等价django的mark_safe ,
  • 2.extends,include一模一样

【1】渲染变量

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% for k,v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详细</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

【2】变量的循环

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% for k,v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详细</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

【3】逻辑判断

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>用户列表</h1>
    <table>
        {% if name %}
          <h1>Hello {{ name }}!</h1>
        {% else %}
          <h1>Hello World!</h1>
        {% endif %}
    </table>
</body>
</html>

【4】相比较Django

  • 比django中多可以加括号,执行函数,传参数
from flask import Flask,render_template,Markup,jsonify,make_response
app = Flask(__name__)

def func1(arg):
    return Markup("<input type='text' value='%s' />" %(arg,))
@app.route('/')
def index():
    return render_template('index.html',ff = func1)

if __name__ == '__main__':
    app.run()

【四】Session

【1】使用

  • flask中得session,没有在服务端存储数据的---》后期扩展,可也把session存到redis中

  • 全局session

    • 放值:session['key']=value
    • 取值:session.get('key')
    • 删除值:session.pop('username', None)

【2】session的运行机制

(1)django

  • 1 生成一个随机字符串
  • 2 把数据保存到djagno-session表中
  • 3 把随机字符串返回给前端--》当cookie存到浏览器中了--》浏览器再发请求,携带cookie过来
  • 4 根据随机字符串去表中查---》转到request.session中

(2)flask

  • 1 把数据加密转成字符串: eyJuYW1lIjoibHF6In0.ZMnbJw.ZUceSaD0kGnU97tu9ZWm3380r00
  • 2 以cookie形式返回给前端---》保存到浏览器中
  • 3 浏览器再发请求,携带cookie过来
  • 4 加密符串---》解密---》放到session对象中

【3】源码分析

  • flask默认使用:SecureCookieSessionInterface作为session的类
  • 请求来了
    • 客户端带了cookie---》取出cookie 中session对应的值
    • 使用解密方式对它进行解密
    • 放到session对象中
  • 请求走了
    • 把用户放到session中得数据
    • 加密---》转成字符串--》以cookie形式返回给前端
  • SecureCookieSessionInterface的方法e:
    • open_session:请去来了用
    • save_session:请求走了用

首先,当服务器接收到一个请求时:

  • 服务器生成一个随机字符串作为Session ID。
  • 服务器将Session ID和对应的数据保存到后端的存储系统中,例如内存、数据库或者Redis等。在Flask中,默认的存储方式是使用SecureCookieSessionInterface。
  • 服务器将Session ID通过Cookie的形式返回给客户端浏览器,并设置有效期。
  • 客户端浏览器将此Cookie保存起来。

然后,当客户端发送下一个请求时:

  • 浏览器自动在请求头中携带Session ID对应的Cookie。
  • 服务器接收到请求后,解析Cookie,获取Session ID。
  • 根据Session ID,在存储系统中查找对应的Session数据,并将其加载到当前请求的上下文中,以便在请求处理过程中使用。

最后,当请求处理完毕时:

  • 服务器将需要在下一个请求中使用的Session数据重新保存到存储系统中。这通常是通过调用save_session方法实现的。
  • 需要注意的是,Flask中的Session数据是以字典的形式存储的,可以通过类似session['key']的方式访问和修改数据。
  • 同时,也提供了session.get('key')方法来安全访问Session数据,以防止出现KeyError。

【4】简单示例

from flask import Flask, session

app = Flask(__name__)
app.secret_key = 'your-secret-key'  # 设置密钥,用于加密Session数据

@app.route('/')
def hello():
    # 设置Session数据
    session['username'] = 'John'
    return 'Hello, World!'

@app.route('/user')
def get_user():
    # 获取Session数据
    username = session.get('username')
    if username:
        return f'Current user: {username}'
    else:
        return 'User not found'

if __name__ == '__main__':
    app.run()
  • 在这个例子中,当访问根路径/时,会设置Session中的usernameJohn
    • 而当访问/user路径时,会从Session中获取username的值并返回。
  • 需要注意的是,在使用Session之前,需要设置一个秘钥secret_key,用于对Session数据进行加密和解密操作,确保数据的安全性。
posted @ 2023-08-26 21:40  Chimengmeng  阅读(60)  评论(0编辑  收藏  举报
/* */