Flask 路由、请求、会话

准备

每日一问:

  1. flask里面加载配置的方法有几种
    5种
    from_mappig
    from_object
    from_json
    from_envval
    from_pyfile
  2. @app.route() 有几个参数
    2个 分别是rule和method
  3. 视图接收来自客户端的请求数据,request有几个属性可以接收?
    在这里插入图片描述

创建python虚拟环境

mkvirtualenv flask -p python3 #创建
deactivate					#退出

在这里插入图片描述
安装:

pip install flask==0.12.5

在这里插入图片描述
已经安装过了所以是这样的显示

创建flask项目

在这里插入图片描述
去settings →project:flask → python Interpreter
在这里插入图片描述
找到自己创建虚拟环境下的 /home/yanmu/.virtualenvs/flask/bin/python3.8 然后点ok就行

在这里插入图片描述
在这里插入图片描述
pycharm环境配置完成

flask 基本运行

# 导入Flask类
from flask import Flask

"""
import_name      Flask程序所在的包(模块),传 __name__ 就可以
                 其可以决定 Flask 在访问静态文件时查找的路径
static_path      静态文件访问路径(不推荐使用,使用 static_url_path 代替)
static_url_path  静态文件访问路径,可以不传,默认为:/ + static_folder
static_folder    静态文件存储的文件夹,可以不传,默认为 static
template_folder  模板文件存储的文件夹,可以不传,默认为 templates
"""
# 创建应用对象
app = Flask(__name__)


# 加载项目配置
class Config(object):
    DEBUG = True


# flask中支持多种配置方式,通过app.config来进行加载,我们会在这里调用常用的配置类
app.config.from_object(Config)


# 编写路由视图
# flask的路由是通过给视图添加装饰器的方式进行编写的。当然也可以分离到另一个文件中。
# flask的视图函数,flask中默认允许通过return返回html格式数据给客户端。
@app.route('/')     # 声明路由
def index():    # 声明视图函数
    return "<h2 style='color:blue'>hello world!</h2>"    # 直接通过return返回普通字符串


# 使用 app.add_url_rule() 方法注册 index() 函数,其作用与前例相同,是一种很传统的方式
# def index():
# 	return "<h2 style='color:blue'>hello world!</h2>"
# app.add_url_rule('/', 'index', index)


if __name__ == '__main__':
    # 运行flask# 启动项目,不要在run 后面写任何代码,不会被执行到
    app.run(host='0.0.0.0', port=8000)  # 指定服务器IP和端口号  wsgiref模块提供的

路由参数的传递与接收

1.什么是路由?
路由: 一种访问地址[url]和应用程序[视图]进行一对一绑定的映射关系
往往在开发中,我们所说的路由,其实通常指代完成路由绑定关系的路由类

from flask import Flask

app = Flask(__name__)


class Config():
    DEBUG = True


app.config.from_object(Config)

# 传递路由参数没有限定类型
# @app.route(rule='/user/<user_id>-<mobile>') # 没有限定参数的类型,所以user_id可以是数字,也可以是其他类型的信息
# def index(user_id,mobile):
#     return 'user_id={},mobile={}'.format(user_id,mobile)


# 接收参数并使用内置转换器
@app.route(rule='/user/<int:user_id>')   # 使用flask内置的路由参数转换器
def user(user_id):
    print(user_id)
    return '%s' % user_id
# flask系统自带转换器编写在werkzeug.routing.py文件中
#     DEFAULT_CONVERTERS = {
#         "default": UnicodeConverter,
#         "string": UnicodeConverter,   默认类型,接受不带斜杠的任何文本
#         "any": AnyConverter,
#         "path": PathConverter,        接收`string`但也接受斜线
#         "int": IntegerConverter,      接受正整数
#         "float": FloatConverter,      接受正浮点值
#         "uuid": UUIDConverter,        接受UUID(通用唯一识别码)字符串  xxxx-xxxx-xxxxx-xxxxx
#     }


if __name__ == '__main__':
    app.run(host='0.0.0.0',port=8001)

自定义匹配路由

from flask import Flask
from werkzeug.routing import BaseConverter  # 1.引入BaseConverter路由参数转换器基类

app = Flask(__name__)


'''
# 方法一
class MobileConverter(BaseConverter):
    regex = r"1[3-9]\d{9}"          # 2.指定自定义匹配的路径    
    
    def __init__(self,*args, **kwargs):
        super().__init__(*args, **kwargs)


# 3. 注册路由参数转换到app应用对象中
app.url_map.converters['mobile'] = MobileConverter


# 编写路由与视图
@app.route(rule='/user/<mobile:user_mobile>')
def user(user_mobile):
    print(user_mobile)
    return '{}'.format(user_mobile)


# 方法二
# 自定义路由参数转换器
class RegexConveerter(BaseConverter):
    def __init__(self,map,*args):
        super().__init__(map)
        self.regex = args[0]


# 注册路由参数转换到app应用对象中
app.url_map.converters['re'] = RegexConveerter


# 编写路由和视图
@app.route(rule="/user/<re('\d{6}'):mobile>")
def user(mobile):
    print(mobile)
    return '{}'.format(mobile)
'''


# 方法三
class MobileConverster(BaseConverter):
    def __init__(self,*args,**kwargs):
        self.regex = r'[123]\d{2}'
        super().__init__(*args,**kwargs)


# app.url_map.converters["使用别名"] = 转换器类名
app.url_map.converters['mob'] = MobileConverster


@app.route(rule='/user/<mob:user_id>')
def user(user_id):
    print(user_id)
    return "{}".format(user_id)


if __name__ == '__main__':
    app.run(debug=True,host='0.0.0.0',port=8001)

http的请求与响应

路由限定请求方式:

from flask import Flask,request
# 限制客户端的http请求方法,注意这里与django不一样,flask并没有默认没有内置csrf攻击防范
@app.route(rule="/user", methods=["post","put","get","delete","patch"])
def user():
    
    # 例如:地址栏中通过  http://127.0.0.1:5000/user?user=1 返回本视图
    
    print(request.method) # 获取本次客户端的http请求方法         GET
    print(request.query_string)  # 获取本次客户端的查询字符串    b'user=1'
    print(request.path)  # 获取本次客户端请求的路由路径部分[去掉域名端口]    /user
    print(request.url) # 获取本次客户端请求的http url地址        http://127.0.0.1:5000/user?user=1
    # 直接从请求中取到请求方式并返回
    return request.method

常用的属性如下:在这里插入图片描述
获取请求中各项数据

from flask import Flask,request
from urllib.parse import parse_qs
from werkzeug.routing import BaseConverter
app = Flask(__name__)

# 路由转换器对路由参数的类型进行限定
# @app.route(rule="/",methods=["POST","PUT","PATCH","DELETE"])
# @app.route(rule="/") # 没有填写第二个参数methods则默认只能通过get请求访问
# def index():
#     return "ok index"


@app.route(rule='/user',methods=['get','put','post','patch','delete'])
def user():
    print(request.method)       # 获取本次客户端的http请求方法         GET
    print(request.path)         # 获取本次客户端请求的路由路径部分[去掉域名端口]    /user
    print(request.url)          # 获取本次客户端请求的http url地址     http://0.0.0.0:8000/user?user_id=11&qwq=22&qwq=33&111=qqq
    print(request.json)         # 获取json数据   {'username': 'xiaohuihui'}
    print(request.files)        # ImmutableMultiDict([('video1', <FileStorage: 'demo.mp4' ('video/mp4')>)])
    print(request.files.get("avatar"))       # 获取ajax或者表单中的上传文件都需要使用request.files<FileStorage: 'timg.jpeg' ('image/jpeg')>
    
    # 获取请求头
    print(request.headers)                      # 获取请求头 Content-Type: application/json ,User-Agent: PostmanRuntime/7.26.5........
    print(request.headers.to_wsgi_list())       # [('Username', 'qwq'), ('Content-Type', 'application/json'), ('User-Agent', 'PostmanRuntime/7.26.5'), ('Accept', '*/*'), ('Postman-Token', '417ed7d2-4101-48b5-8d35-7614a2f62050'), ('Host', '0.0.0.0:8000'), ('Accept-Encoding', 'gzip, deflate, br'), ('Connection', 'keep-alive'), ('Content-Length', '38')]
    # to_list() 将在1.0版中删除 改用 to_wsgi_list()
    print(request.headers.get('Host'))          # 获取请求头,REMOTE_ADDR客户端的地址 0.0.0.0:8000
    print(request.headers.get('username'))      # 获取自定义请求头,首字母大写 qwq
    print(request.is_json)                      # 是否是ajax请求
    
    # 获取html表单,视图必须支持post方法访问
    print(request.form)                         # 表单中的全部数据
    print(request.form.get("username"))         # 表单单个数据
    # 获取ajax或者表单中的上传文件都需要使用request.files
    print(request.files.get("avatar"))          # <FileStorage: 'timg.jpeg' ('image/jpeg')>
    
    
    # 获取查询数据字符串
    print(request.query_string)                         # 获取本次客户端的(原始)查询字符串 b'user_id=11&qwq=22&qwq=33&111=qqq'
    query_string = parse_qs(request.query_string)
    print('query_string:',query_string)                 # query_string: {b'user_id': [b'11'], b'qwq': [b'22', b'33'], b'111': [b'qqq']}
    print(query_string['qwq'.encode()][0].decode())     # 22
    print(request.args)                                 # 获取本次客户端的(Dict字典)查询字符串     ImmutableMultiDict([('user_id', '11'), ('qwq', '22'), ('qwq', '33'), ('111', 'qqq')])
    print(request.args.get('qwq'))                      # 提取一个值 22
    print(request.args.getlist('qwq'))                  # 提取多个值 ['22', '33']
    print(request.args.to_dict())                       # {'user_id': '11', 'qwq': '22', '111': 'qqq'}
    
    """
     ImmutableMultiDict的实例对象 提供了四个常用的方法给我们获取数据,
     1. get 获取指定参数的第一个值
     2. getlist 获取指定参数的多个值
     3. to_dict 把所有参数转换成字典[request对象的部分属性不支持]
     4. to_list 把所有参数转换成列表[request对象的部分属性不支持]
     """

    return 'ok'


class Config():
    DEBUG = True


app.config.from_object(Config)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8000)

响应数据格式与页面跳转:

from flask import Flask,request,make_response,jsonify,Response,redirect,url_for


app = Flask(__name__)


# 一、页面跳转
@app.route("/")
def index():
    # 页面跳转
    # return redirect("http://www.baidu.com") # 跳转到站外
    return redirect("/user") # 跳转到站内
    # return redirect(url_for("user",user_id=100)) # 通过url_for指定视图名称,直接找到对应路由进行跳转

    # 跳转的原理,实际就是利用HTML文档中的元信息
    # response = make_response()
    # response.headers["Location"] = "http://www.baidu.com"
    # response.headers["Company"] = "oldboy"  # 自定义响应头
    # response.status_code = 302 # 自定义响应状态吗
    # return response


# 二、页面反回的数据或格式
@app.route(rule='/user')
def user():

    # 默认直接可以通过return返回html文本
    # return "<h2 style='color:blue'>hello world!</h2>"
    # return make_response("<h2 style='color:blue'>hello world!</h2>" )        # 等同于上面的一段
    # return Response("<h2 style='color:blue'>hello world!</h2>")           # make_response本质上就是Response
   
    # 返回json格式数据
    # data = {"name":"xiaoming","age":13}
    # return jsonify(data)
    
    # 关于Response常用的参数
    # Response(response='内容', status=‘http响应状态码’, headers=自定义响应头,mimetype="数据格式" )

    # 识别身份
    # if request.args.get("user") == "abc":
    #     # 也可以返回图片,压缩包 等其他在浏览器能支持的数据,既可以支持显示图片,也可以支持显示
    #     with open("2.jpg", "rb") as f:
    #         content = f.read()
    #         response = make_response(content)
    #         response.headers["Content-Type"] = "image/jpeg"
    #         return response
    # else:
    #     return "没有权限"
    # 支持下载
    # with open("123.zip", "rb") as f:
    #     response.headers["Content-Type"] = "application/zip"
    #     return response
    
    # 返回图片信息
    with open('1.png','rb') as f:
        content = f.read()
    return Response(response=content,status=201,mimetype="image/png")
    
    # 返回文件
    # with open('./1.zip',"rb") as f:
    #     content=f.read()
    # # 判断权限,身份...
    # return Response(response=content,mimetype="application/zip")
class Config():
    DEBUG = True


app.config.from_object(Config)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)

http的会话控制

因为 http 是一种无状态协议,浏览器请求服务器是无状态的。

无状态:指一次用户请求时,浏览器、服务器无法知道之前这个用户做过什么,每次请求都是一次新的请求。

无状态原因:浏览器与服务器是使用 socket 套接字进行通信的,服务器将请求结果返回给浏览器之后,会关闭当前的 socket 连接,而且服务器也会在处理页面完毕之后销毁页面对象。

有时需要保持下来用户浏览的状态,比如用户是否登录过,浏览过哪些商品等

实现状态保持主要有两种方式:

  • 在客户端存储信息使用Cookie,token[jwt,oauth]
  • 在服务器端存储信息使用Session

Cookie

Cookie是由服务器端生成,发送给客户端浏览器,浏览器会将Cookie的key/value保存,下次请求同一网站时就发送该Cookie给服务器(前提是浏览器设置为启用cookie)。Cookie的key/value可以由服务器端自己定义。

使用场景: 登录状态, 浏览历史, 网站足迹,购物车 [不登录也可以使用购物车]

Cookie是存储在浏览器中的一段纯文本信息,建议不要存储敏感信息如密码,因为电脑上的浏览器可能被其它人使用

Cookie基于域名安全,不同域名的Cookie是不能互相访问的

如访问luffy.com时向浏览器中写了Cookie信息,使用同一浏览器访问baidu.com时,无法访问到luffy.com写的Cookie信息

浏览器的同源策略针对cookie也有限制作用.

当浏览器请求某网站时,会将本网站下所有Cookie信息提交给服务器,所以在request中可以读取Cookie信息

设置和获取 cookie:

设置cookie需要通过flask的Response响应对象来进行设置,由响应对象会提供了方法set_cookie给我们可以快速设置cookie信息。

from flask import Flask,make_response,Response,request

app = Flask(__name__)


# 设置cookie
@app.route('/set_cookie')
def set_cookie():

    # resp = make_response("ok")
    resp = Response("this is to set cookie", status=202)     # 等同于上面  status=202返回的状态嘛
    # response.set_cookie(key="变量名",value="变量值",max_age="有效时间/秒")
    resp.set_cookie('username','xx',max_age=3600)
    return resp


# 获取cookie
@app.route('/get_cookie')
def get_cookie():
    print(request.cookies)
    """打印效果:
     {'username': 'xx'}
    """
    resp = request.cookies.get('username')
    print(resp)     # 'xx'
    print(app.session_cookie_name)      # session 
    return Response(response=resp)


# 删除cookie():
@app.route('/del_cookie')
def del_cookie():
    response = make_response('删除成功! ok')
    response.set_cookie("username", '',0)
    return response


class Config():
    DEBUG = True


app.config.from_object(Config)


if __name__ == '__main__':
    app.run(host='0.0.0.0',port=8080)
设置and获取 session
from flask import Flask, session, Response, request
from datetime import timedelta
import os
app = Flask(__name__)


# 设置session
@app.route('/set_session')
def set_session():
    session.permanent = True
    app.permanent_session_lifetime = timedelta(seconds=10)      # 设置十秒过期
    session['username'] = 'this is session'
    session['info'] = {                 # 支持python基本数据类型作为值
        'age': 8,
        "sex": True,
    }
    return Response(response=session['username'])


# 获取session
@app.route('/get_session')
def get_session():
    print(session.get('username'))
    print(session.get('info'))
    print(app.session_cookie_name)      # app.config中session_cookie_name的配置项   打印 session
    return session.get('username')


# 设置secret_key(密钥)的三种方式
class Config():
    SECRET_KEY = "12332112aaa"      # 自定义设置密钥
    DEBUG = True


app.config.from_object(Config)
# app.config['SECRET_KEY'] = os.urandom(24)         # os.urandom(24)随机生成一个密钥
# app.secret_key = os.urandom(24)
# app.config.update(SECRET_KEY = os.urandom(24))

# 查看当前flask默认支持的所有配置项
# print(app.config)
"""
<Config {
 'DEBUG': False,
 'TESTING': False,
 'PROPAGATE_EXCEPTIONS': None,
 'PRESERVE_CONTEXT_ON_EXCEPTION': None,
 'SECRET_KEY': None,
 'PERMANENT_SESSION_LIFETIME': datetime.timedelta(31),
 'USE_X_SENDFILE': False,
 'LOGGER_NAME': '__main__',
 'LOGGER_HANDLER_POLICY': 'always',
 'SERVER_NAME': None,
 'APPLICATION_ROOT': None,
 'SESSION_COOKIE_NAME': 'session',
 'SESSION_COOKIE_DOMAIN': None,
 'SESSION_COOKIE_PATH': None,
 'SESSION_COOKIE_HTTPONLY': True,
 'SESSION_COOKIE_SECURE': False,
 'SESSION_REFRESH_EACH_REQUEST': True,
 'MAX_CONTENT_LENGTH': None,
 'SEND_FILE_MAX_AGE_DEFAULT': datetime.timedelta(0, 43200),
 'TRAP_BAD_REQUEST_ERRORS': False,
 'TRAP_HTTP_EXCEPTIONS': False,
 'EXPLAIN_TEMPLATE_LOADING': False,
 'PREFERRED_URL_SCHEME': 'http',
 'JSON_AS_ASCII': True,
 'JSON_SORT_KEYS': True,
 'JSONIFY_PRETTYPRINT_REGULAR': True,
 'JSONIFY_MIMETYPE': 'application/json',
 'TEMPLATES_AUTO_RELOAD': None
"""


if __name__ == '__main__':
    app.run(host='0.0.0.0',port=8080)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值