什么是URL?
URL是统一资源定位符,对可以从互联网上得到的资源的位置和访问方法的一种简洁的表示,是互联网上标准资源的地址;
互联网上的每个文件都有一个唯一的URL;
基本URL包含模式(或称协议)、服务器名称(或IP地址)路径和文件名
scheme://host[:port#]/path/.../[;url-params][?query-string][#anchor]
https://www.mi.com
http://i1.mifile.cn/a4/xmad_15481237431678_LbHXJ.jpg
https://docs.djangoproject.com/en/1.11/topics/http/urls/
url协议
http——超文本传输协议资源
https——用安全套接字层传送的超文本传输协议
ftp——文件传输协议
常见的HTTP请求方式
GET:可以用浏览器直接访问;请求可以携带参数,但是有长度限制;请求参数直接放在URL后面。
POST:不能使用浏览器直接访问;对请求参数的长度没有限制;可以用来上传文件等需求。
HTTP常见状态码
1xx :信息,服务器收到请求,需要请求者继续执行操作。
2xx :成功,操作被成功接收并处理。
3xx :重定向,需要进一步的操作以完成请求。
4xx :客户端错误,请求包含语法错误或无法完成请求。
5xx :服务器错误,服务器在处理请求的过程中发生了错误。
常见的HTTP状态码:
200 - 请求成功
301 - 资源(网页等)被永久转移到其它URL
404 - 请求的资源(网页等)不存在
500 - 内部服务器错误
url配置和路由
from flask import Flask
app = Flask(__name__)
@app.route('/')
@app.route('/index')
def hello_world():
return 'Hello Flask!'
if __name__ == '__main__':
app.run()
其中hello_world这个函数叫做一个视图函数(view)
url与视图函数的关系
路由的配置
方式1:使用装饰器
语法规则
@app.route(url,methods)
参数解释
url:匹配的URL地址
methods:所支持的请求方式([‘GET’,‘POST’])
示例:
@app.route(‘/login’,methods[‘GET’,‘POST’])
方式2:使用API配置
语法规则
app.add_url_rule(url, url name, view_name)
参数解释
url:匹配的URL地址
url_name:给URL的命名
view_name:视图函数
路由匹配规则
匹配整个文字
@app.route(‘/hello’)
传递参数
@app.route(‘/user/’)
指定参数类型
@app.route(‘/post/int:post_id’)
url参数类型
查看url规则列表
app.url_map
URL逆向解析
根据名称解析成URL字符串
<1>url_for(url_name,**kwargs)
<2>静态文件(js/css/图片)引用
url_for(‘static’,filename=‘style.css’)
视图函数中获取页面传值
URL中的值
@app.route(/page/‘)
def list_user(page):
URL中的值为可选
@app.route(/page/’)
def list_user(page=None):
from flask import Flask
app = Flask(__name__)
@app.route('/') # 关键代码
@app.route('/index')
def hello_world():
return 'Hello Flask!'
@app.route('/user/<page>')
def list_user(page):
return '您好,您当前在第{}页'.format(page)
if __name__ == '__main__':
app.run(debug=True)
打开 http://127.0.0.1:5000/
打开127.0.0.1:5000/user/1
打开127.0.0.1:5000/user/100
有个问题,不输入page会报错
可以在程序加入page的默认值和无page时的装饰器
@app.route('/user/')
@app.route('/user/<page>')
def list_user(page=1):
return '您好,您当前在第{}页'.format(page)
这样,不输入page的话page默认为1
请求和响应
在网页上输入127.0.0.1:5000/index,会向服务器发送请求,然后服务器返回响应,使该网址的页面上展示内容。
分派
在网页上输入127.0.0.1:5000/index,找到对应的装饰器@app.route(‘/index’),再找到其后的视图函数进行执行。
上下文对象
在分派请求之前激活应用上下文和请求上下文,在请求处理完成后将其删除。
应用上下文对象
current_app
当前应用的实例
from flask import Flask,current_app
app = Flask(__name__)
@app.route('/index')
def index():
print(app)
print(current_app)
print(app==current_app)#True
print(app is current_app)#False
return 'index'
g
处理请求时的临时存储对象,每次请求都会重设这个变量
请求对象
request:请求对象,封装了客户端发出的HTTP请求中的内容
session:用户会话(dict),各请求之间的数据共享
请求报文常用参数
method:请求的类型(GET/POST/OPTION等)
form:POST请求数据dict
args:GET请求数据dict
values:POST请求和GET请求数据集合dict
files:上传的文件数据dict
cookies:请求中cookie dict
headers:HTTP请求头
请求报文练习—获取GET参数
from flask import Flask, render_template,request
import os
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/html')
def html():
'''把html文件的内容在浏览器展现出来'''
return render_template('index.html')
@app.route('/show/html')
def html_show():
'''理解渲染机制'''
file_name = os.path.join(os.path.dirname(__file__), 'templates', 'index.html')
print(file_name)
return file_name
@app.route('/test/req')
def test_request():
'''请求报文练习'''
get_args=request.args
print(get_args)
# page=request.args.get('page')
#页码一定是正整数
page = request.args.get('page',1)
print('page',page)
name=request.args.get('name')
print('name',name)
return 'request success'
if __name__ == '__main__':
app.run(debug=True)
打开http://127.0.0.1:5000/test/req
http://127.0.0.1:5000/test/req?page=1&name=张三
请求报文练习—解析请求头中的IP地址
from flask import Flask, render_template, request
import os
app = Flask(__name__)
@app.route('/')
def index():
return 'index'
@app.route('/test/req')
def test_request():
'''请求报文练习'''
get_args = request.args
print(get_args)
# page=request.args.get('page')
# 页码一定是正整数
page = request.args.get('page', 1)
print('page', page)
name = request.args.get('name')
print('name', name)
# 获取服务器所在的主机地址
headers = request.headers
# print(headers)
print(headers.get('host')) # 127.0.0.1:5000
# 获取IP地址—实际业务中可进行恶意IP的拦截
ip = request.remote_addr
print('远程IP地址\n', ip) # 127.0.0.1
# 获取uer_agent
user_agent=request.headers.get('User-Agent',None)
print('uer_agent信息\n',user_agent)
#Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
return 'request success'
if __name__ == '__main__':
app.run(debug=True)
请求钩子
思考:如下场景如何实现?
<1>每个请求中都要验证用户信息(是否已登,是否有权限访问)
<2>限制来着某些IP的恶意请求
使用钩子函数可以减少重复代码的编写,便于维护
before_first_request
服务器初始化后第一个请求到达前执行
before_request
每一个请求到达前执行
@app.before_first_request
def first_request():
"""服务器启动后第一个请求到达"""
print('first request')
@app.before_request
def per_request():
"""每一个请求到达前"""
print('before request')
服务器重启打印first request,每次访问都会打印before request
其它
after request每次请求处理完成后执行,如果请求过程中产生了异常,则不执行;
teardown_request每次请求处理完成之后执行,如果请求过程中产生了异常也执行。
响应
可以是字符串,可以是元组(tuple),(response,status,headers)或(response,headers)
<1>response——响应内容
<2>status——响应状态码
@app.route('/tet/response')
def test_response():
"""测试响应"""
return 'response success', 201
<3>headers——响应头信息
@app.route('/tet/response')
def test_response():
"""测试响应"""
return 'response success', 201,{'user_id':'my_id'}
使用make response代替以上(更简单)
from flask import Flask, request,make_response
@app.route('/tet/response')
def test_response():
"""测试响应"""
# return 'response success', 201,{'user_id':'my_id'}
#构造一个响应对象
resp=make_response('这是一个响应对象',403,{'token':'abcdef0001'})
resp.headers['user_id'] = 'my_id_0001'
#resp.status_code = 200
return resp
响应html
@app.route('/tet/response')
def test_response():
#响应html
html="<html><body><h1 style='color:#foo'>HTML文本显示</h1></body></html>"
resp=make_response(html)
return resp
实际使用中,将htm写到程序中太繁琐,通常通过从文件中响应html:
from flask import Flask, render_template, request,make_response
@app.route('/tet/resp/html')
def test_html():
"""从文件中响应html"""
html=render_template('index.html')
resp=make_response(html,400)
return resp
重定向
理解
比如在登陆状态,发表评论,突然退出了登陆状态,网页被重定向到首页。
redirect()实现重定向
abort()处理错误
from flask import Flask, abort
@app.route('/')
def shouye():
abort(404)
from flask import Flask, abort
@app.route('/')
def shouye():
abort(403)
触发403警告时,展示指定内容
@app.errorhandler(403)
def forbidden_page(err):
"""无权限访问界面"""
print(err)
return '您没有权限访问本页面,请联系管理员进行权限开通'
ip拦截
@app.route('/')
def shouye():
ip_list_forbidden =['127.0.0.2']#ip黑名单
ip=request.remote_addr#获取用户ip
if ip in ip_list_forbidden:
abort(403)
return 'hello'
@app.errorhandler(403)
def forbidden_page(err):
"""无权限访问界面"""
print(err)
return '您没有权限访问本页面,请联系管理员进行权限开通'
@app.route('/')
def shouye():
ip_list_forbidden =['127.0.0.1']#ip黑名单
ip=request.remote_addr#获取用户ip
if ip in ip_list_forbidden:
abort(403)
return 'hello'
@app.errorhandler(403)
def forbidden_page(err):
"""无权限访问界面"""
print(err)
return '您没有权限访问本页面,请联系管理员进行权限开通'