Flask入门教程(非常详细),从零基础入门到精通,看完这一篇就够了


**转义字符**



转义字符过滤器

转义前的数据是:{ { info | safe }} {% autoescape true %} { {info }} {% endautoescape %}

**其它过滤器**



其它过滤器

绝对值:{ { -6 | abs }}
小数: { { 6 | float }}
字符串:{ { 6 | string }}
格式化:{ {'%s--%s' | format('我' , '你')}}
长度:{ {'我是九,你是三,除了你,还是你'|length}}
最后一个:{ {'我是九,你是三,除了你,还是你'|last}}
第一个:{ {'我是九,你是三,除了你,还是你'|first}}
统计次数: { {'我是九,你是三,除了你,还是你' | wordcount }}
替换:{ {'===我是九,你是三,除了你,还是你 ====' |replace('我是九,你是三,除了你,还是 你' ,'拿着,这个无限额度的黑卡,随便刷')}}


> 
> **小提示**
> 
> 
> jinja2模板 默认全局开启了自动转义功能
> 
> 
> * safe 过滤器:可以关闭一个字符串的自动转义
> * escape 过滤器:对某一个字符串进行转义
> * autoescape 标签,可以对他包含的代码块关闭或开启自动转义
> 	+ {% autoescape true/false %} 代码块 {% endautoescape %
> 
> 
> 


**自定义过滤器**


只有当系统提供的过滤器不符合需求后,才须自定义过滤器 过滤器本质上就是一个函数。 如果在模版中调用这个过滤器,那么就会将这个变量的值作为第一 个参数传给过滤器这个函数, 然后函数的返回值会作为这个过滤器的返回值。 需要使用到一个装饰器: @app.template\_filter(‘过滤器名称’)


**自定义数据替换过滤器**


例如:将新闻中出现的 所有“ 我是九你是三,除了你还是你” 换成 “你不用多好,我喜欢就好”



#将模版设置为自动加载模式
app.config[‘TEMPLATES_AUTO_RELOAD’]=True
@app.template_filter(‘cut’)
def cut(value):
value=value.replace(“我是九你是三,除了你还是你”,‘你不用多好,我喜欢就好’)
return value



使用自定义过滤器:{ {新闻内容值|cut}}


**自定义时间过滤器**


例如:操作发布新闻 与现在的时间间隔



from datetime import datetime
#需求:操作发布新闻 与现在的时间间隔
@app.template_filter(‘handle_time’)
def handle_time(time):
“”"
time距离现在的时间间隔
1. 如果时间间隔小于1分钟以内,那么就显示“刚刚”
2. 如果是大于1分钟小于1小时,那么就显示“xx分钟前”
3. 如果是大于1小时小于24小时,那么就显示“xx小时前”
4. 如果是大于24小时小于30天以内,那么就显示“xx天前”
5. 否则就是显示具体的时间 2030/10/2016:15
“”"
if isinstance(time, datetime):
now = datetime.now()
timestamp = (now - time).total_seconds()
if timestamp < 60:
return “刚刚”
elif timestamp >= 60 and timestamp < 60 * 60:
minutes = timestamp / 60
return “%s分钟前” % int(minutes)
elif timestamp >= 60 * 60 and timestamp < 60 * 60 * 24:
hours = timestamp / (60 * 60)
return ‘%s小时前’ % int(hours)
elif timestamp >= 60 * 60 * 24 and timestamp < 60 * 60 * 24 * 30:
days = timestamp / (60 * 60 * 24)
return “%s天前” % int(days)
else:
return time.strftime(‘%Y/%m/%d %H:%M’)
else:
return time



发布时间:{ {新闻创建时间|handle_time}}


### 流程控制-选择结构


![dc2a05958f524fc9be0f242da8243e04.png](https://img-blog.csdnimg.cn/dc2a05958f524fc9be0f242da8243e04.png)


所有的控制语句都是放在 {% … %} 中,并且有一个语句 {% endxxx %} 来进 行结束!


\*\*if:\*\*if语句和python中的类似,可以使用 >,=,==,!= 来进行判 断,也可以通过 and,or,not,() 来进行逻辑合并操作



{% if age >= 18 %}

{ { age }}岁,成年人,可以通宵打游戏


{% else %}

{ { age }}岁,未成年人,可以通宵学习


{% endif %}


> 
> **注意**:
> 
> 
> if 条件判断语句必须放在 {% if statement %} 中间,并且还必须有结束 的标签 {% endif %} 。
> 
> 
> 


### 流程控制-循环结构


![d219e517da9248db88137e15eb850390.png](https://img-blog.csdnimg.cn/d219e517da9248db88137e15eb850390.png)


for…in… for循环可以遍历任何一个序列包括列表、字典、元组。并且 可以进行反向遍历,以下将用几个例子进行解释:


**列表**



  • {% for user in users%}
  • { { user}}
  • {% endfor %}

**遍历字典**



{% for key in person.keys() %} { { key}} {% endfor %} {% for val in person.values() %} { { val}} {% endfor %} {% for item in person.items() %} { { item}} {% endfor %} {% for key,value in person.items() %} { { value}} {% endfor %}

如果序列中没有值的时候,进入else 反向遍历用过滤器 reverse:



  • {% for user in users|reverse %}
  • { { user}}
  • {% else %}
  • 没有任何用户
  • {% endfor %}

并且Jinja中的for循环还包含以下变量,可以用来获取当前的遍历状 态:


![c740855d2ca540d2b7e3cc265449d8bd.png](https://img-blog.csdnimg.cn/c740855d2ca540d2b7e3cc265449d8bd.png)



> 
> **总结**
> 
> 
> 在 jinja2 中的 for 循环,跟 python 中的 for 循环基本上是一模一样的 也是 for…in… 的形式。并且也可以遍历所有的序列以及迭代器 唯一不同的是, jinja2 中的 for 循环没有 break 和 continue 语句
> 
> 
> 


### 导入模板include


![47a5e37a9d604dc8bdd0cf45dc471ec5.png](https://img-blog.csdnimg.cn/47a5e37a9d604dc8bdd0cf45dc471ec5.png)


1. 这个标签相当于是直接将指定的模版中的代码复制粘贴到当前位 置。


2. include 标签,如果想要使用父模版中的变量,直接用就可以了,不 需要使用 with context 。


3. include 的路径,也是跟 import 一样,直接从 templates 根目录下去找, 不要以相对路径去找。



SXT {% include "common/head.html" %}
这是首页内容 { { major }}

{% include "common/footer.html" %}

### set与with标签


![8ee042840b684909be1c3d185c2c3c13.png](https://img-blog.csdnimg.cn/8ee042840b684909be1c3d185c2c3c13.png)


**set的使用**


在模版中,可以使用 set 语句来定义变量



{% set uname=‘sxt’%}

用户名:{ { uname }}


一旦定义了这个变量,那么在后面的代码中,都可以使用这个变 量,就类似于Python的变量定义是一样的


**with语句**


with 语句定义的变量,只能在 with 语句块中使用,超过了这个代码 块,就不能再使用了



{% with classroom=‘python202’%}

班级:{ { classroom }}


{% endwith %}


> 
> **注意**
> 
> 
> 关于定义的变量, with 语句也不一定要跟一个变量, 可以定义一个空的 with 语句, 需要在指定的区域才能使用的情况,可以set与with组合使用。
> 
> 
> 



{% with %}
{% set pname=‘李思思’ %}

娱乐县县长:{ { pname }}

{% endwith %}

### 静态文件


![a7a9840af7c44f439f358750cadd08f2.png](https://img-blog.csdnimg.cn/a7a9840af7c44f439f358750cadd08f2.png)


**静态文件**:css文件 js文件 图片文件等文件


加载静态文件使用的是 url\_for 函数。然后第一个参数需要为 static ,第 二个参数需要为一个关键字参数 filename=‘路径’ 。


**语法**



{ { url_for(“static”,filename=‘xxx’) }}


![80251f1219494d7e8104a17c2000b38f.png](https://img-blog.csdnimg.cn/80251f1219494d7e8104a17c2000b38f.png)



> 
> **注意** 路径查找,要以当前项目的 static 目录作为根目录
> 
> 
> 


### 模板继承


![c7e7c937215149a083c2e478cb88998a.png](https://img-blog.csdnimg.cn/c7e7c937215149a083c2e478cb88998a.png)


**为什么需要模版继承**


模版继承可以把一些**公用的代码**单独抽取出来放到一个父模板中 以后**子模板直接继承**就可以使用了。 这样可以**重复的利用代码**,并且以后**修改起来**也比较方便


![966f551b5aeb4348807348d632ecda5a.png](https://img-blog.csdnimg.cn/966f551b5aeb4348807348d632ecda5a.png)


**模版继承语法**


使用 extends 语句,来指明继承的父模板。父模板的路径,也是相对 于 templates 文件夹下的绝对路径



{% extends “base.html” %}


**block语法**


一般在父模版中,定义一些公共的代码。子模板可能要根据具体的 需求实现不同的代码。这时候父模版就应该有能力提供一个接口,让子模板来实现。从而 实现具体业务需求的功能。


**父模板**



{% block block的名字 %}
{% endblock %}


**子模板**



{% block block的名字 %}
子模板中的代码
{% endblock %}


**调用父模版代码block中的代码**


默认情况下,子模板如果实现了父模版定义的block。那么子模板 block中的代码就会覆盖掉父模板中的代码。 如果想要在子模板中仍然保持父模板中的代码,那么可以使用 {
  { super( ) }} 来实现


**父模板**



{% block block_body %}

我是父模版block_body处的内容


{% endblock %}

**子模板**



{% block block_body%}
{ { super() }}

我是子模版block_body处的内容


{% endblock %}

**调用另外一个block中的代码**


如果想要在另外一个模版中使用其他模版中的代码。那么可以通过 {
  { self.其他block名字() }} 就可以了



{% block title %}
sxt首页
{% endblock %}
{% block block_body%}
{ { self.title() }}

我是子模版block_body处的内容


{% endblock %}


> 
> **注意**
> 
> 
> 1. 子模板中的代码,第一行,应该是 extends
> 
> 
> 2. 子模板中,如果要实现自己的代码,应该放到block中。如果 放到其他地方,那么就不会被渲染
> 
> 
> 


## Flask视图


### **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)


### 类视图


![ee0d25996054498489f7b1f54a2485be.png](https://img-blog.csdnimg.cn/ee0d25996054498489f7b1f54a2485be.png)


之前我们接触的视图都是函数,所以一般简称函数视图。 其实视图也可以基于类来实现,类视图的好处是支持继承, 但是类视图不能跟函数视图一样,写完类视图还需要通过 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’:‘zs’,‘lua’:‘Python’},
{‘name’:‘lisi’,‘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)


### 基于调度方法的类视图


![7980062125ca4f7eb26eb286ce8318f0.png](https://img-blog.csdnimg.cn/7980062125ca4f7eb26eb286ce8318f0.png)


1. 基于方法的类视图,是根据请求的 method 来执行不同的方法的。 如果用户是发送的 get 请求,那么将会执行这个类的 get 方法。 如果用户发送的是 post 请求,那么将会执行这个类的 post 方法。其他 的method类似,比如 delete 、 put


2. 这种方式,可以让代码更加简洁。所有和 get 请求相关的代码都放 在 get 方法中,所有和 post 请求相关的代码都放在 post 方法中。就不 需要跟之前的函数一样,通过 request.method == ‘GET’



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==“sxt” and pwd ==“123”:
return render_template(‘index.html’)
else:
return self.get(error=“用户名或者密码错误”)

注册类视图

app.add_url_rule(‘/login/’,view_func=LoginVi
ew.as_view(‘my_login’))


HTML



账号:
密码:
{# { { error }}#} {# 优化写法 :判断 #} {% if error %} { { error }} {% endif %}

### 装饰器


![2d59a3ecb74a470583e8b73f725e5ab7.png](https://img-blog.csdnimg.cn/2d59a3ecb74a470583e8b73f725e5ab7.png)


简言之,python装饰器就是用于拓展**原来函数功能**的一种函数,这 个**函数的特殊之处在于它的返回值也是一个函数**, 使用python装饰器的**好处**就是在不用更改原函数的代码前提下给函 数增加新的功能。


1. 在视图函数中使用自定义装饰器,那么自己定义的装饰器必须放 在 app.route 下面。 否则这个装饰器就起不到任何作用。


**案例1**


需求:查看设置个人信息时,只有检测到用户已经登录了才能查 看,若没有登录,则无法查看并给出提示信息


定义装饰器



def login_required(func):
@wraps(func)
def wrapper(*arg,**kwargs):
uname = request.args.get(‘uname’)
pwd = request.args.get(‘pwd’)
if uname == ‘zs’ and pwd == ‘123’:
logging.info(f’{uname}:登录成功’)
return func(*arg,**kwargs)
else:
logging.info(f’{uname}:尝试登录,但没成功’)
return ‘请先登录’
return wrapper


使用装饰器



@app.route(‘/settings/’)
@login_requierd
def settings():
return ‘这是设置界面’


2. 在类视图中使用装饰器,需要重写类视图的一个类属性 decorators , 这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰 器。


**案例2**


**需求**: 查看设置个人信息时,只有检测到用户已经登录了才能查看, 若没有登录,则无法查看并给出提示信息


使用装饰器



class ProfileView(views.View):
decorators = [login_requierd]
def dispatch_request(self):
return ‘这是个人中心界面’

app.add_url_rule(‘/profile/’,view_func=ProfileView.as_view(‘profile’))


### **蓝图介绍**


在Flask中,使用蓝图Blueprint来分模块组织管理。 蓝图实际可以理解为是存储一组视图方法的容器对象,其具有如下 特点:


* 一个应用可以具有多个Blueprint
* 可以将一个Blueprint注册到任何一个未使用的URL下比如 “/user” 、 “/goods”
* Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应 用的视图和函数的
* 在一个应用初始化时,就应该要注册需要使用的Blueprint



> 
> **注意**
> 
> 
> Blueprint并不是一个完整的应用,它不能独立于应用运行,而 必须要注册到某一个应用中
> 
> 
> 


**使用方式**


使用蓝图可以分为三个步骤


* 1 创建一个蓝图对象



user_bp=Blueprint(‘user’,name)


* 在这个蓝图对象上,



@user_bp.route(‘/’)
def user_profile():
return ‘user_profile’


* 在应用对象上注册这个蓝图对象



app.register_blueprint(user_bp)


**指定蓝图的url前缀**


在应用中注册蓝图时使用 url\_prefix 参数指定



app.register_blueprint(user_bp,url_prefix=‘/user’)
app.register_blueprint(goods_bp,url_prefix=‘/goods’)


### 蓝图的目录结构


为了让项目代码更加清晰,可以通过将代码分在不同的文件里进行 管理


**根据功能模块**


对于一个打算包含多个文件的蓝图,通常将创建蓝图对象放到 Python包的 \_\_init\_\_.py 文件中



--------- project # 工程目录
|------ main.py # 启动文件
|------ user #用户蓝图
| |— init.py # 此处创建蓝图对象
| |— view.py
| |— …
|------ goods # 商品蓝图
| |— init.py
| |— …
|…


**根据技术模块**



--------- project # 工程目录
|------ main.py # 启动文件
|------ view #用户蓝图
| |— user.py # 此处创建蓝图对象
| |— item.py
| |— view.py
| |— …
|…


### 蓝图中模版文件


![1ff2fe4856c646bea13433e229037597.png](https://img-blog.csdnimg.cn/1ff2fe4856c646bea13433e229037597.png)


**寻找规则**


* 如果项目中的templates文件夹中有相应的模版文件,就直接使 用了。
* 如果项目中的templates文件夹中没有相应的模版文件,那么就 到在定义蓝图的时候指定的路径中寻找。
	+ 并且蓝图中指定的路径可以为相对路径,相对的是当前这个蓝图文件所在的目录


![2b6f67ce5f384f0d87afed3e5f39596c.png](https://img-blog.csdnimg.cn/2b6f67ce5f384f0d87afed3e5f39596c.png)


因为这个蓝图文件是在user/view.py,那么就会到blueprints这个 文件夹下的user\_page文件夹中寻找模版文件。


**小总结:** 常规:蓝图文件在查找模版文件时,会以templates为根目录进行 查找



> 
> **注意**
> 
> 
> * 1 个性化coder喜欢在【创建蓝图对象的时候】 指定 模版文 件的查找路径,如下 news\_bp =Blueprint(‘news’,\_\_name\_\_,url\_prefix=‘/news’,template\_folder=‘news\_page’)
> * 2 只有确定templates目录下没有对应的 html文件名的时候, 才会去蓝图文件指定的目录下查找,指定才会生效
> * 3 若templates目录下,有一个与蓝图文件指定的目录下同名 的一个 html文件时,优先走templates目录下的东西
> 
> 
> 


### **蓝图中静态文件**


![74e75038b81c4038bb759c4d55dadeac.png](https://img-blog.csdnimg.cn/74e75038b81c4038bb759c4d55dadeac.png)


蓝图内部静态文件 蓝图对象创建时不会默认注册静态目录的路由。需要我们在创建时 指定 static\_folder 参数。 下面的示例将蓝图所在目录下的 static\_admin 目录设置为静态目录:



user=Blueprint(“user”,name,static_folder=‘user_static’)
app.register_blueprint(admin,url_prefix=‘/user’)


也可通过 static\_url\_path 改变访问路径



user =Blueprint(‘user’,name,template_folder=‘user_page’,static_folder=‘user_static’,static_u
rl_path=‘/static’)
app.register_blueprint(user,url_prefix=‘/user’)



> 
> **总结** 【掌握】查找方式1:查找静态文件时,正常情况下,会以 static为根目录进行查找 【了解】查找方式2:查找静态文件时,非正常情况下,需要用 url\_for(‘蓝图的名字.static’),然后会去蓝图对象在创建时指定的 静态文件夹目录下 去查找静态文件
> 
> 
> 


### 蓝图url\_for函数


![ad3532f75bca41179f32327da8290b53.png](https://img-blog.csdnimg.cn/ad3532f75bca41179f32327da8290b53.png)


如果使用蓝图,那么以后想要反转蓝图中的视图函数为url,就应该 在使用url\_for的时候指定这个蓝图名字。 app类中、模版中、同一个蓝图类中都是如此。否则就找不到这个 endpoint


html文件中



新闻列表 OK写法
{# 新闻列表 no Ok写法#}


python文件中



from flask import
Blueprint,render_template,url_for
user_bp=Blueprint(‘news’,name,url_prefix=‘/user’,template_folder=‘user_page’,static_folder=‘user_static’)
@user_bp.route(‘/list/’)
def user_list():
#如下写法:才找得到 url_for(‘蓝图名称.方法名’)
print(url_for(‘user.user_list’)) #/user/list/
print(url_for(‘user.user_detail’)) #/user/detail/
return render_template(‘user_list.html’)
@user_bp.route(‘/detail/’)
def user_detail():
return ‘用户详情页面’


### 子域名实现


蓝图实现子域名:


1. 使用蓝图技术。


2. 在创建蓝图对象的时候,需要传递一个 subdomain 参数,来指定这 个子域名的前缀。



cms_bp=Blueprint(‘cms’,name,subdomain=‘cms’)


3. 需要在主app文件中,需要配置app.config的SERVER\_NAME参 数。例如:



app.config[‘SERVER_NAME’]=‘baidu.com:5000’


4. 在windows: C:\Windows\System32\drivers\etc 下,找到hosts文件,然后添 加域名与本机的映射。Linux: /etc/hosts 域名和子域名都需要做映射



> 
> **注意** ip地址不能有子域名 localhost也不能有子域名
> 
> 
> 


## Flask高级


### Flask设置Cookie


![9debf43221344405a7e0e4a60568ac7b.png](https://img-blog.csdnimg.cn/9debf43221344405a7e0e4a60568ac7b.png)


**设置**


设置cookie是在Response的对象上设置。 flask.Response 对象有一个 set\_cookie 方法,可以通过这个方法来设置 cookie 信息。


key,value形式设置信息



from flask import Flask, make_response
app = Flask(name)
@app.route(‘/cookie’)
def set_cookie():
resp = make_response(‘set cookie ok’)
resp.set_cookie(‘uname’, ‘itbaizhan’)
return resp


**查看Cookie**


在Chrome浏览器中查看cookie的方式:


方式1:借助于 开发调式工具进行查看


方式2:在Chrome的设置界面->高级设置->内容设置->所有 cookie->找到当前域名下的cookie。



from flask import request
@app.route(‘/get_cookie’)
def get_cookie():
resp = request.cookies.get(‘uname’)
return resp


**删除cookie**


方式1:通过 Response对象.delete\_cookie ,指定cookie的key,就可以删 除cookie了。



from flask import request
@app.route(‘/delete_cookie’)
def delete_cookie():
response = make_response(‘helloworld’)
response.delete_cookie(‘uname’)
return response


方式2:在客户端浏览器人为的删除(清除浏览器浏览历史记录 后,很多网站之前免密登录的都不好使了)


**Cookie的有效期**


**默认的过期时间**:如果没有显示的指定过期时间,那么这个cookie 将会在浏览器关闭后过期。 **max\_age**:以秒为单位,距离现在多少秒后cookie会过期。


**expires**:为datetime类型。这个时间需要设置为格林尼治时间, 相对北京时间来说 会自动+8小时 如果max\_age和expires都设置了,那么这时候以max\_age为标 准。



> 
> **注意**
> 
> 
> max\_age在IE8以下的浏览器是不支持的。 expires虽然在新版的HTTP协议中是被废弃了,但是到目前为 止,所有的浏览器都还是能够支持,所以如果想要兼容IE8以下 的浏览器,那么应该使用expires,否则可以使用max\_age。
> 
> 
> 



from flask import Flask,Response
app = Flask(name)
@app.route(‘/’)
def index():
return ‘Hello!!’
@app.route(‘/create_cookie/defualt/’)
def create_cookie1():
resp = Response(‘通过默认值,设置cookie有效期’)

如果没有设置有效期,默认会在浏览器关闭的时候,让cookie过期

resp.set_cookie(‘una

你可能感兴趣的:(flask,ios,python)