文章目录

1 什么是url?

url是统一资源定位符(Uniform Resource Locator的简写),对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。

一个URL由以下几部分组成:

scheme://host:port/path/?parameter=xxx#anchor
https://www.baidu.com/Public/linux/?fr=aladdin#23
  • scheme:代表的是访问的协议,一般为http或者https以及ftp等。
  • host:主机名,域名,比如www.baidu.com。
  • port:端口号。当你访问一个网站的时候,浏览器默认使用80端口。
  • path:路径。比如:www.baidu.com/Public/linux/?python=aladdin#23,www.baidu.com后面的Public/linux就是path。
  • query-string:查询字符串,比如:www.baidu.com/s?wd=python,?后面的python=aladdin就是查询字符串。
  • anchor:锚点,后台一般不用管,前端用来做页面定位的。比如:https://www.oldboyedu.com/Public/linux/?fr=aladdin#23 ,#后面的23就是锚点

2 为什么要有url?

顾名思义统一资源定位符,是用来做定位用的,我们的web开发无非是要调用程序,而调用的具体程序我们称之为python的视图函数,URL建立了与Python视图函数一一对应的映射关系,通俗易懂可以理解为一条命令触发了一个python的函数或类。

3 如何应用url?

3.1 url和路由的区别。

我们调用接口需要调用的是一段具体的代码,也就是一个python类或者python函数,而url就是对这段代码的具体映射,也就是说我们可以通过url找到一个具体的python类或者python函数,这便是url。而路由是根据url定位到具体的pyhon类或python函数的程序,这段程序我们称之为路由。

在Flask程序中使用路由我们称之为注册路由,是使用程序实例提供的app.route()装饰器注册路由,而括号内的字符串就是url,注册路由的过程就是完成了 url和python类或函数映射的过程,可以理解为会有一张表保存了url与python类或函数的对应关系。这样我们以url访问flask就可以找到对应的程序。
例:

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

按照这种关系我们再写一个路由

@app.route('/student_list/')
def student_list():
return 'students'

3.2 url传参的两种

3.2.1动态路由传参

如果你仔细观察日常所用服务的某些URL格式,会发现很多地址中都包含可变部分。例如,你想根据学生的id找到具体的学生,http://127.0.0.1:5000/student_list/<student_id>/ 仍然在path部分 ,但是你没必要写多个路由,我们Flask支持这种可变的路由。
见代码:

@app.route('/student_list/<student_id>/')
def student_list(student_id):
return '学生{}号的信息'.format(student_id)

关键字:在path中有可变的部分 ,达到了传参的效果,我们称之为动态路由传参

3.2.1.1 动态路由的过滤

可以对参数限定数据类型,比如上面的文章详情,限定student_id必须为整数类型

@app.route('/student_list/<int:student_id>/')
def article_detail(student_id):
return '学生{}号的信息'.format(student_id)

主要有这几种类型过滤:
  string: 默认的数据类型,接收没有任何斜杠"\ /"的字符串
  int: 整型
  float: 浮点型
  path: 和string类型相似,但是接受斜杠,如:可以接受参数/aa/bb/cc/多条放在一起
  uuid: 只接受uuid格式的字符串字符串,
提示:uuid为全宇宙唯一的串

上面几种约束均为如下格式,例子中的int可以换为 string,float,path,uuid

@app.route('/student_list/<int:student_id>/')
def article_detail(student_id):
return '学生{}号的信息'.format(student_id)

any: 可以指定多种路径,如下面的例子
url_path的变量名是自己定义的

@app.route('/<any(student,class):url_path>/<id>/')
def item(url_path, id):
if url_path == 'student':
return '学生{}详情'.format(id)
else:
return '班级{}详情'.format(id)


动态路由的适用场景?
如果想增加网站的曝光率,可以考虑使用动态路由,因为是把path作为参数,搜索引擎的算法会定义你为一个静态页面,不会经常改变,有利于搜索引擎的优化。但是如果是公司内部的管理系统就没有必要使用动态路由,因为内部系统对曝光率没有要求。
上面我们接受参数使用的是path(路径)形式,这种传参的形式就叫动态路由传参,有利于搜索引擎的优化。

3.2.2 查询字符串传参

我们上面介绍了什么是查询字符串:
如果我们在浏览器中输入www.baidu.com/s?wd=python&ad=flask的参数,这个 ? 后的key=value便是查询字符串, 可以写多个key=value用&相连我们将查询字符串作为参数去请求我们的flask程序,这便是查询字符串传参。
我们之前再注册路由的时候会在里面的path部分以及函数的形参设置参数来接受path的参数,我们在查询字符串传参的时候需要从flask模块里面导入request对象,用request.args属性在我们的程序中根据查询字符串的key取出查询字符串的value
argsrequest的一个属性,其本质是一个Werkzeug依赖包的的immutableMultiDict的对象,用于解析我们传入的查询字符串,immutableMultiDict对象也继承了Dict类,所以可以使用字典的.get()方法来获取,当然了如果我们有获取原生未解析的原生查询字符串的需求,可以使用query_string属性。
例:

from flask import Flask,request
...
@app.route('/student_name/')
def school_name_list():
name = request.args.get('name')
age = request.args.get('age') return "学生的姓名为{},年龄为{}".format(name, age)

3.3 url_for()的使用:

3.3.1简介视图函数:

我们在访问一个网址的时候在调用flask项目的时候需要调用的是一段具体的代码,也就是一个python类或者python函数,在这里这个python类我们称之为视图类,python函数我们称之为视图函数。

3.3.2 url_for()的作用:

如果我们在视图函数中想使用一个url,比如给前端返回,或者我们在这个视图函数中返回一个模板文件都会使用到url,url相当于一把钥匙可以开启一些资源。如果你修改了注册路由编写的url规则,相当于修改了钥匙。那么其他的视图函数依旧是使用了原来的钥匙就无效了,如果项目是一个大项目,你一点点手动的去改涉及到的的url就不合理了。url_for()就是用来解决这个问题的。

3.3.3url_for()的原理:

利用视图函数名字一般不会改变的特性,利用视图函数的名字去动态精准的获取url,以便于开发使用。

url_for('视图函数名字')   # 输出该视图函数url

具体例子

from flask import Flask,url_for

app = Flask(__name__)
app.config.update(DEBUG=True) @app.route('/')
def demo1():
print(url_for("book")) # 注意这个引用的是视图函数的名字 字符串格式
print(type(url_for("book"))) return url_for("book") @app.route('/book_list/')
def book(): return 'flask_book' if __name__ == "__main__":
app.run()

我们直接访问http://127.0.0.1:5000/,经过路由的分发会触发demo1的执行。如图

3.3.4 url_for如何处理动态的视图函数?

如果想获取动态路由,必须以关键字实参的形式为动态的path部分赋值,注意动态的path部分必须被赋值,
案例:

@app.route('/demo2/')
def demo2(): student_url = url_for('student', id=5, name='mark') # id 就是动态path的key 必须赋值, # name 将作为查询字符串传入
print(student_url) return student_url @app.route('/student/<int:id>/')
def student(id):
return 'student {}'.format(id)

控制台输出:

浏览器输出:

3.3.5 url_for如何为url添加查询字符串?

如果想在路径后面拼出来查询字符串,以关键字实参的形式放到url_for()里面作为参数,会自动拼成路径
案例:

@app.route('/demo3/')
def demo3():
school_url = url_for('school', school_level='high', name='college')
# 具体要拼接的查询参数 以关键字实参的形式写在url_for里
print(school_url) return school_url @app.route('/school/')
def school(): return 'school message'

控制台输出:

浏览器输出:

3.4 自定义动态路由过滤器

3.4.1 自定义动态路由过滤器之正则匹配

我们可以通过继承werkzeug.routing 的BaseConverter类从而自己定义一个动态路由过滤器的规则

from flask import Flask,request
from werkzeug.routing import BaseConverter app = Flask(__name__)
app.debug =True class TelephoneConverter(BaseConverter):
regex = '1[3857]\d{9}' #右下斜杠d app.url_map.converters['tel'] = TelephoneConverter @app.route('/student/<tel:telenum>/')
def student_detail(telenum): return '学生的手机号码是{}'.format(telenum) if __name__ == '__main__':
app.run()

注意:

  1. 1. 自定义动态路由过滤器类,该类必须继承`werkzeug.routing` 的`BaseConverter`类 2. 通过`regex`属性指定路由规则 3. 讲自定义的类映射到`app.url_map.converters`中(其本质是一个字典) `app.url_map.converters['tel'] = TelephoneConverter`

实现效果: ![](https://img-blog.csdnimg.cn/img_convert/b0c003c7a0292324ad15564443bd83f6.png)

3.4.2 自定义动态路由过滤器之处理动态路由

自定义一个类,该通过继承werkzeug.routing 的BaseConverter类不光可以实现正则匹配,我们介绍一下以下两个方法:

  • * 在该类中实现 to_python 方法: 这个方法的返回值,将会传递给视图函数的形参。我们可以利用这个方法实现处理url中动态路由部分。 * 在该类中实现 to_url 方法: 翻转url的时候也就是使用url_for函数的时候,我们传入指定的动态路由部分,触发to_url方法,这个方法的返回值,会拼接在非动态路由上,从而实现生成符合要求的url格式。

![](https://img-blog.csdnimg.cn/img_convert/0aae9de3bf0aa652b925afee187c9c9c.png)

实例:
from flask import Flask,request,url_for
from werkzeug.routing import BaseConverter app = Flask(__name__)
app.debug =True class ListConverter(BaseConverter):
regex = '.*' # 这个regex代表都匹配的意思,可以根据自己的需求制定url规则
def to_python(self, value):
'''这个函数用于拿到了路由里的动态参数赋值给value,
可以在to_python进行操作动态参数,
返回操作完的的结果给视图函数的形参'''
return value.split('+') def to_url(self, value):
'''这个函数用于和url_for连用,
url_for通过指定给动态参数(以关键字实参的形式)赋值给value
我们可以根据我们的需求操作url_for传进来的参数,
然后返回一个理想的动态路由内容拼接在url上'''
return '+'.join(value) app.url_map.converters['list'] = ListConverter @app.route('/student_list/<list:students>/')
def student_list(students):
print(url_for('student_list',students=['a','b'])) # 输出 /student_list/a+b/ return '{}'.format(students) if __name__ == '__main__':
app.run()

证明to_python()方法把访问时候动态路由部分被处理成列表了。

证明我们的 to_url() 方法把url_for()函数传入的动态路由部分由列表转换成拼接字符串了。

2 HTTP请求

1 请求报文和响应报文

打开浏览器,当我们输入一个url,点击访问的时候会向目标服务器发送一个HTTP请求,请求的的时候会发生什么呢,会经过os七层,这里我们不赘述os七层通讯原理,可以理解为通过url我们请求目标服务器的一段具体的资源,可以理解为发送了一个请求,一个请求的本质就是向目标服务器上面发送了一些数据,这种浏览器于服务器之间交互的数据被称为报文。

  • * 请求报文:请求时浏览器发送的数据称为请求报文 * 响应报文:服务器收到了请求返回给浏览器的数据称为响应报文 *提示:这里我们们是BS架构去讲解, BS架构就是浏览器和后端服务器的交互,CS架构是客户端和服务端的交互,BS架构可以理解为CS架构的一个具体实现。浏览器就是客户端,后端服务器就是服务端。*

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

报文中的GET请求和POST请求

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

**报文实例:** ```python ''' GET请求报文 # 请求首行 GET / HTTP/1.1\r\n # get请求后面的参数 GET /?name=lqz&age=18 HTTP/1.1\r\n # 请求头 Host: 127.0.0.1:8008\r\n Connection: keep-alive\r\n Cache-Control: max-age=0\r\n Upgrade-Insecure-Requests: 1\r\n User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\n Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nAccept-Encoding: gzip, deflate, br\r\n Accept-Language: zh-CN,zh;q=0.9\r\n Cookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n' # 请求体(get请求,请求体为空) ''' '''

POST请求报文
# 请求首行
POST /?name=lqz&age=18 HTTP/1.1\r\n
# 请求头
Host: 127.0.0.1:8008\r\nConnection: keep-alive\r\n
Content-Length: 21\r\nCache-Control: max-age=0\r\n
Origin: http://127.0.0.1:8008\r\nUpgrade-Insecure-Requests: 1\r\n
Content-Type: application/x-www-form-urlencoded\r\n
User-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36\r\n Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\nReferer: http://127.0.0.1:8008/?name=lqz&age=18\r\n
Accept-Encoding: gzip, deflate, br\r\nAccept-Language: zh-CN,zh;q=0.9\r\nCookie: csrftoken=7xx6BxQDJ6KB0PM7qS8uTA892ACtooNbnnF4LDwlYk1Y7S7nTS81FBqwruizHsxF\r\n\r\n
# 请求体
name=lqz&password=123' '''
  ![](https://img2018.cnblogs.com/blog/1825659/201910/1825659-20191009222153150-801230202.png)

### 2 request对象
#### 2.1什么是request对象?
request对象封装解析了请求报文中的数据,其大部分功能是由依赖包werkzeug完成的,并且每个request对象都是线程隔离的,保证了数据的安全性。
#### 2.2为什么要有request对象?
request对象解决了很多问题,各种请求的方法以及请求参数的格式都不一致,所以flask帮我们做了一个request对象,专门去解析各种方法以及各种格式的请求,以便于去开发使用。
#### 2.3 requst对象的常用方法
request对象使用需要从flask模块中导入
```python
from flask import Flask, request
2.3.1 使用request属性获取url

访问: http://127.0.0.1:5000/student_list/?name=mark :
表2-1 使用request的属性获取url

属性 解析值 属性 解析值
path u‘/student_list/’ base_url u’http://127.0.0.1:5000/student_list/’
full_path u‘/student_list/?name=mark’ url u’http://127.0.0.1:5000/student_list/?name=mark’
host u’127.0.0.1:5000’ url_root u’http://127.0.0.1:5000/’
host_url u’http://127.0.0.1:5000/’

request的解析结果如下。

@app.route('/student_list/')
def student_list():
print(request.path) # 输出 /student_list/
print(request.full_path) # 输出 /student_list/?name=mark
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=mark
print(request.url_root) # 输出 http://127.0.0.1:5000/ return 'request.urldemo测试'
2.3.2 其他request对象常用的属性和方法。

request里面有诸多的方法,先对requests这些方法有个初步印象,随着我们日后的学习会慢慢接触到这些request常用的方法。

3 GET和post的实例:

3.1 常见的HTTP方法见下表:

请求 说明 请求 说明
GET 获取服务器资源 DELETE 删除服务器资源
POST 处理服务器资源 PATCH 在服务器更新资源(客户端提供改变的属性)
PUT 在服务器更新资源(客户端提供改变后的完整资源)

一般常用的请求为GET和POST

3.2 GET请求:

GET请求一般用于在服务器上获取资源,不会更改服务器的状态。
GET实例

@app.route('/', methods=['GET'])  # 不写methods也可以 默认就接收get请求
def demo_get():
print(request.args.get('name')) # 输出 mark return '{}请求'.format(request.method)

结合request对象,使用request.args属性获取get传来的参数,关于args我们在上一章已经论述过了。
关键词

  • * 使用request.args属性获取get传来的参数,关于args我们在上一章已经论述过了。 * @app.route('/', methods=['GET']) 指定浏览器只能以GET方法访问服务端。

#### 3.3 POST请求: **POST 请求: 会给服务器提交一些数据或者文件,会对服务器的状态产生影响。** 在了解POST请求之前我们先了解一下render_termplate ##### 3.3.1 render_template的简单使用 ```python from flask import Flask, request, render_template ``` 我们暂时只简单的理解render_template模块可以把html文件返回给浏览器并渲染。 如: ![](https://img-blog.csdnimg.cn/img_convert/77dfc7b710f22d6a468170cb20570954.png)

server.py

from flask import Flask, request, render_template
...
@app.route('/login/',methods=['GET'])
def login():
return render_template('login.html')
...

注意:render_template()会去flask根目录下的templates里面寻找文件,所以给的参数路径是相对路径。
关键词:render_template()中放的文件路径是与templates文件夹相对的路径
templates/login.html

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录界面</title>
</head>
<body>
<form action="/login_request/" method="POST">
用户:<input type="text" name="username">
密码:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>

关键词

  • * form标签的`action`指定的是跳转的页面。并且会自动拼接成http://127.0.0.1:5000/login_request/ ​ 也就是本项目的: ip地址+端口+/login_request/ * form标签的`method`指定的是以什么方法请求服务端,此案例中请求的方法为POST方法。

访问127.0.0.1:5000/login/ 后如下图 ![](https://img-blog.csdnimg.cn/img_convert/0387a64e979ce142782afa165b0ae5ab.png)

3.3.2 正式开始我们的POST案例:

项目目录:

server.py

from flask import Flask, request, render_template
import config app = Flask(__name__) @app.route('/login_request/',methods=['POST'])
def login_request():
print(request.form.get('username')) # 'mark'
print(request.form.get('password')) # '123'
if request.form.get('username') == 'mark' and request.form.get('password') == '123':
return 'success'
else:
return 'error' @app.route('/login/',methods=['GET'])
def login():
return render_template('login.html') if __name__ == '__main__':
app.run()

关键词

  • * request.form是专门用来针对表单取数据的,在这里如果前端是以表单的形式提交的,我们可以使用request.form来取值 * @app.route() 中的 methods=['POST'] 代表只接收浏览器的POST请求

**templates/login.html** ```python
登录界面 用户: 密码: ``` ![](https://img-blog.csdnimg.cn/img_convert/e2f06fbe479d24228ce20358e2df883d.png)

总体的逻辑是 :

  1. 1. 首先访问127.0.0.1:5000/login/,默认是get请求。 2. 然后`return render_template('login.html')` 返回给浏览器页面。 3. 然后填写内容点击提交,以post方式请求 [http://127.0.0.1:5000/login_request/。](http://127.0.0.1:5000/login_request/%E3%80%82) 4. 然后进入`def login_request()`视图函数 进行逻辑判断返回成功与否。

#### 3.4 一个视图函数同时可以接收GET和POST请求 我们的案例和3.3.2案例完成的业务逻辑是一样的,相当于简化了3.3.2的案例,把两个视图函数合并到一起,利用`request.method`属性可以获取字符串格式的请求方法。来区分本次请求是GET还是POST 实例: **server.py**: ```python from flask import Flask, request, render_template import config

app = Flask(name)

@app.route(‘/login_inner/’,methods=[‘POST’,‘GET’])
def login_inner():
if request.method == ‘GET’: #判断本次请求是否为get请求
return render_template(‘login.html’)
if request.form.get(‘username’) == ‘mark’ and request.form.get(‘password’) == ‘123’:
return ‘success’
return ‘error’

if name == ‘main’:
app.run(debug=True)

**关键词**:
<ul>
* `@app.route()`的`methods`方法 指定该视图函数接收浏览器传过来的请求方法,可以指定多个。
* `request.method`获取字符串格式的请求方法
</ul>

**templates/login.html**:
```python
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录界面</title>
</head>
<body>
<form action="" method="POST">
用户:<input type="text" name="username">
密码:<input type="text" name="password">
<input type="submit" value="提交">
</form>
</body>
</html>

其展示效果

3 视图函数和视图类

1 视图函数

之前我们已经了解过了视图函数的大概用法,本节深入了解一下视图函数

1.1 endpoint简介

endpint参数是写在注册路由的装饰器中的一个参数,学名叫端点,我们可以理解为函数的别名。原来我们翻转视图函数的url的时候是直接通过是如函数的名字,如url_for('函数名'),现在我们可以指定一个endpoint='fbv'参数来进行翻转url。如果不指定endpoint,默认就以函数名作为端点名。
实例:

@app.route('/fbvtest/',methods=['GET','POST'],endpoint='fbv')
def fbvtest():
url_demo = url_for('fbv')
return '利用视图函数别名翻转的url为:{}'.format(url_demo)

关键词:
利用@app.route()endpoint='fbv'参数可以自由指定端点名,url_for可以根据指定的端点名进行翻转。

1.2 装饰器注册路由源码浅析

(1) 首先写一个小视图函数

#注册装饰器的原理
#1 v = app.route('/source_code_demo/',endpoint='source_code')
#2 v(source_code_demo)
@app.route('/source_code_demo/',endpoint='source_code')
def source_code_demo(): return 'source_code_demo'

(2) 查看app.route()源码

...
def route(self, rule, **options):
...
def decorator(f):
endpoint = options.pop('endpoint', None)
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator

解析:

  • * ,发现`route()`返回的是`decorator`函数地址,然后基于语法糖和装饰器的原理,decorator会加括号运行,像这样`decorator(source_code_demo)` * `decorator`函数中首先取出`endpoint`,然后运行`self.add_url_rule(rule, endpoint, f, **options)` * **所以** `self.add_url_rule(rule, endpoint, f, **options)`**就是注册路由的核心**

**(3)** 点进`self.add_url_rule(rule, endpoint, f, **options)`查看源码, ​ 再点进`_endpoint_from_view_func(view_func)`查看源码 ```python ...

@setupmethod
def add_url_rule(self, rule, endpoint=None, view_func=None,
provide_automatic_options=None, **options):

   if endpoint is None:
endpoint = _endpoint_from_view_func(view_func)
options['endpoint'] = endpoint
methods = options.pop('methods', None) # if the methods are not given and the view_func object knows its
# methods we can use that instead. If neither exists, we go with
# a tuple of only ``GET`` as default.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',) ...

```python
def _endpoint_from_view_func(view_func):
"""Internal helper that returns the default endpoint for a given
function. This always is the function name.
"""
assert view_func is not None, 'expected view func if endpoint ' \
'is not provided.'
return view_func.__name__

解析:

  • * 由上述代码我们可以直到如果没有指定`endpoint`,我们调用了 `_endpoint_from_view_func()` * 观察`_endpoint_from_view_func`函数我们可以知道,返回了视图函数的名字给了`endpoint`赋值 * `methos`没有指定会给methos赋默认值`('GET',)`

**小结:**

  1. 1. `self.add_url_rule(rule, endpoint, f, options)`就是注册路由的核心 2. 观察`_endpoint_from_view_func`函数我们可以知道,返回了视图函数的名字给了`endpoint`赋值 3. `methos`没有指定会给`methods`赋默认值`('GET',)`

![](https://img-blog.csdnimg.cn/img_convert/c4757c6557deef01b794dea25f424cb1.png) ## 1.3 另一种注册路由的方式---app.add_url_rule() 通过看上一个小节写的源码,现在我们知道了app.route() 的核心就是`self.add_url_rule(rule, endpoint, f, options)`就是注册路由的核心。所以我们可以直接使用`app.add_url_rule()`的方式来注册路由。 **实例:** ```python def add_url_test():

return '实现了add_url方式注册路由'
# url 端点 函数地址

app.add_url_rule(‘/add_url_test/’,endpoint=‘add_demo’,view_func=add_url_test)

![](https://img2018.cnblogs.com/blog/1825659/201910/1825659-20191009223409813-960893827.png)

## 1.4 视图函数中添加自定义装饰器
我们在平时的开发的过程中,很多需要权限验证的功能需要用到装饰器,下面的代码是如何在flask中实现一个装饰器。
```python
from flask import Flask, request
from functools import wraps app = Flask(__name__) def login_verify(func):
@wraps(func)
def wrapper(*args, **kwargs):
user_name = request.args.get('user')
password = request.args.get('password')
if user_name == 'mark' 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
def my_info():
return '个人信息页面'

关键词

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

![](https://img-blog.csdnimg.cn/img_convert/96ab9b39c0725b5fdf47635ed1e13cb9.png)

2 视图类

2.1 视图类的基本写法

from flask import Flask, views, request, url_for
from functools import wraps def login_verify(func):
@wraps(func)
def wrapper(*args, **kwargs):
user_name = request.args.get('user')
password = request.args.get('password')
if user_name == 'mark' and password == '123':
return func(*args,**kwargs)
else:
return '请登录'
return wrapper class CBVTest(views.MethodView): methods = ['GET','POST'] # 指定可以接收的方法有什么
decorators = [login_verify,] # 指定自定义的装饰器 def get(self):
print(url_for('cbvtest'))
return 'cbv_get'
def post(self):
return 'cbv_post'
app.add_url_rule('/cbvtest',view_func=CBVTest.as_view(name='cbvtest'),endpoint='end_demo')

讲解:

  1. 1. 首先从flask中导入 `views` 2. 写一个类一定要继承 `views.MethodView` 3. 在类中写`methods = ['GET','POST']` 可以指定可接受的请求类型 4. 在类中写`decorators = [login_verify,]`可以指定装饰器,第一个装饰器是最里层函数依次往后包裹 5. 在类中写`def get(self):`用于获取get请求 6. 在类中写` def post(self):`用于获取post请求 7. 添加路由的方法使用 app.add_url_rule( '路由',view_func=CBVTest.as_view(name='自定义一个端点名字'))

其原理是CBVTest.as_view(name='自定义一个端点名字')会返回一个函数,name是为这个函数命的名字,可以通过这个函数进行分发请求等操作。

3 详细讲解注册路由的参数:

常用的参数

@app.route和app.add_url_rule参数:
rule, URL规则
view_func, 视图函数名称
endpoint = None, 名称,用于反向生成URL,即: url_for('名称')
methods = None, 允许的请求方式,如:["GET", "POST"]

不常用的参数(了解)

(1) 对URL最后的 / 符号是否严格要求 strict_slashes = False

strict_slashes = False
'''
@app.route('/index', strict_slashes=False)
#访问http://www.xx.com/index/ 或http://www.xx.com/index均可
@app.route('/index', strict_slashes=True)
#仅访问http://www.xx.com/index
'''

(2) 重定向到指定地址redirect_to=“ ”

@app.route("/",redirect_to='/home/')
def index(): return '根路径' @app.route("/home/")
def admin_demo(): return 'home路径'

(3) 为函数提供默认参数值

defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}

**(4)**子域名设置subdomain=“ ”

from flask import Flask,url_for

app = Flask(__name__)
app.debug = True
'''
先在hosts设置域名解析(就是在本机的hosts文件上编辑上域名对应ip的关系)
域名解析会先解析本地如果没有再解析dns服务器
C:\Windows\System32\drivers\etc\hosts 127.0.0.1 mark.com
127.0.0.1 admin.mark.com '''
app.config['SERVER_NAME'] = 'mark.com:5000' # 这个代表访问这个域名的时候要访问5000端口 @app.route("/")
def index(): return '设置域名成功' @app.route("/admin_demo/",subdomain='admin')
def admin_demo(): return '设置子域名成功' '''
在浏览器中访问主域名
mark.com:5000/ 在浏览器中访问子域名
admin.mark.com:5000/admin_demo/ 注意:后面跟的path路径部分正常写
''' if __name__ == '__main__':
app.run(host='127.0.0.1',port=5000) # 测试服务器不稳定,尽量手动制定ip和端口

Flask框架——详解URL、HTTP请求、视图函数和视图类的更多相关文章

  1. python flask框架详解

    Flask是一个Python编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务.本文参考自Flask官方文档, 英文不好的同学也可以参考中文文档 1.安装flask pi ...

  2. [Cocoa]深入浅出 Cocoa 之 Core Data(1)- 框架详解

    Core data 是 Cocoa 中处理数据,绑定数据的关键特性,其重要性不言而喻,但也比较复杂.Core Data 相关的类比较多,初学者往往不太容易弄懂.计划用三个教程来讲解这一部分: 框架详解 ...

  3. Spark2.1.0——内置Web框架详解

    Spark2.1.0——内置Web框架详解 任何系统都需要提供监控功能,否则在运行期间发生一些异常时,我们将会束手无策.也许有人说,可以增加日志来解决这个问题.日志只能解决你的程序逻辑在运行期的监控, ...

  4. Spark2.1.0——内置RPC框架详解

    Spark2.1.0——内置RPC框架详解 在Spark中很多地方都涉及网络通信,比如Spark各个组件间的消息互通.用户文件与Jar包的上传.节点间的Shuffle过程.Block数据的复制与备份等 ...

  5. 深入浅出 Cocoa 之 Core Data(1)- 框架详解

    深入浅出 Cocoa 之 Core Data(1)- 框架详解 罗朝辉(http://blog.csdn.net/kesalin) CC 许可,转载请注明出处 Core data 是 Cocoa 中处 ...

  6. (转) shiro权限框架详解06-shiro与web项目整合(上)

    http://blog.csdn.net/facekbook/article/details/54947730 shiro和web项目整合,实现类似真实项目的应用 本文中使用的项目架构是springM ...

  7. php中流行的rpc框架详解

    什么是RPC框架? 如果用一句话概括RPC就是:远程调用框架(Remote Procedure Call) 那什么是远程调用? 我的官方群点击此处. 通常我们调用一个php中的方法,比如这样一个函数方 ...

  8. Shiro 安全框架详解二(概念+权限案例实现)

    Shiro 安全框架详解二 总结内容 一.登录认证 二.Shiro 授权 1. 概念 2. 授权流程图 三.基于 ini 的授权认证案例实现 1. 实现原理图 2. 实现代码 2.1 添加 maven ...

  9. Flask框架cbv的写法、请求与响应、请求扩展、session源码分析、闪现

    本篇文章将会详细讲在flask框架如何写cbv.请求与响应.请求扩展.session源码分析.闪现等知识点. 目录 一.flask写CBV 二.请求与响应 三.session 四.闪现flash 五. ...

  10. jQuery Validate验证框架详解

    转自:http://www.cnblogs.com/linjiqin/p/3431835.html jQuery校验官网地址:http://bassistance.de/jquery-plugins/ ...

随机推荐

  1. ReactNative原理与核心知识点

    React Native特点 跨平台 使用js写出页面组件代码被React框架统一转成Virtual DOM树,Virtual DOM树是UI结构的一层抽象,可以被转换成任何支持端的UI视图. Rea ...

  2. 基于html2canva jspdf 实现前端页面加水印 并导出页面PDF

    基于html2canva jspdf 实现前端页面加水印 并导出页面PDF; 下载完整代码请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12 ...

  3. Java 递归的小练习,累加、累乘、斐波那契兔子、文件递归

    递归的小练习, public static void main(String[] args) { System.out.println(sum(10)); System.out.println(mul ...

  4. 什么是 CSR、SSR、SSG、ISR - 渲染模式详解

    本文以 React.Vue 为例,介绍下主流的渲染模式以及在主流框架中如何实现上述的渲染模式. 前置知识介绍 看渲染模式之前我们先看下几个主流框架所提供的相关能力,了解的可跳到下个章节. 挂载组件到 ...

  5. 【Azure Event Hub】自定义告警(Alert Rule)用来提示Event Hub的消息incoming(生产)与outgoing(消费)的异常情况

    问题描述 在使用Azure Service Bus的时候,我们可以根据Queue中目前存在的消息数来判断当前消息是否有积压的情况. 但是,在Event Hub中,因为所有消息都会被存留到预先设定的保留 ...

  6. hdfs小文件合并

    HDFS small file merge 1.hive Settings There are 3 settings that should be configured before archivin ...

  7. IRF技术介绍及配置介绍

    IRF技术介绍及配置介绍 IRF(Intelligent Resilient Framework,智能弹性架构)是 H3C 自主研发的软件虚拟化技术. 它的核心思想是将多台设备通过 IRF 物理端口连 ...

  8. 数据处理的那些事「GitHub 热点速览」

    撇开一屏占四分之三屏幕的 AI 相关项目之外,本周剩下的热榜项目就是同数据有关的数据库项目,比如 CockroachDB 团队开源的 kv 存储数据库 pebble,旨在提供高性能的消息队列 blaz ...

  9. Oracle表的导出、导入

    有些情况下,需要单独导出某些表,用或者分析数据. 下面记录Oracle表的导出导入方法 1. 表的导出 ./exp $username/$passwd@$ORACLE_SID file=/$file_ ...

  10. SQL 注入学习手册【笔记】

    SQL 注入基础 [若本文有问题请指正] 有回显 回显正常 基本步骤 1. 判断注入类型 数字型 or 字符型 数字型[示例]:?id=1 字符型[示例]:?id=1' 这也是在尝试闭合原来的 sql ...