第一个flask项目
@app.route(‘/’) # 用到了装饰器 闭包
from flask import Flask
app = Flask(__name__)
@app.route('/') # 用到了装饰器 闭包
def hello_world(): # put application's code here
return '你好,python'
# 1. debug模式:
# 1.1 开启debug模式后,只要修改代码后保存,就会自动重新加载,不需要手动重启项目
# 1.2 如果开发的时候出现bug,开启了debug模式,浏览器可以看到出错信息
#
# 2. 修改host:
# 主要的作用: 让其他电脑能访问到我电脑上的flask项目
#
# 3. 修改端口号:
# 主要的作用: 如果5000被占用,可以修改端口号
if __name__ == '__main__':
app.run()
run参数详解
-
debug 是否开启调试模式, 开启后修改过python代码会自动重启
-
port 启动指定服务器的端口号, 默认是5000
-
host 主机, 默认是127.0.0.1, 指定为0.0.0.0代表本机所以ip
URL与视图映射
基本用法
- url: http[80]/https[443]😕/www.qq.com:443/path
- 根路由 http[80]/https[443]😕/www.qq.com:443/ 没有path
- url与视图: path与视图
#路由route + 视图函数hello_world
@app.route('/') # 这里用到了装饰器 闭包
def hello_world(): # put application's code here
return 'Hello World!'
@app.route("/blog/list")
def blog_list():
return "我是博客列表"
带参数的**url: 将参数固定到了path中
@app.route("/blog/<int:blog_id>")
def blog_detail(blog_id):
return "你访问的博客是: %s" % blog_id
- book/list: 会给我返回第一页的数据
- book/list?page=2: 获取第二页的数据
- 用法:http://127.0.0.1:5000/book/list?page=2
@app.route('/book/list')
def book_list():
#arguments: 参数
#request.args: 类字典类型
#default: 默认值
page = request.args.get("page", default=1, type=int)
return f"你获取的是第{page}页的图书列表"
HTML转义
因为flask的路由函数接收到内容后会默认把他当成html来解析,这样就有可能产生安全问题。所以需要引入escape函数来避免一些不合法的输入
from markupsafe import escape
@app.route("/<name>")
def hello(name):
return f"Hello, {escape(name)}!"
模板渲染
通过导入flask的render_template包,可以进行模板渲染
from flask import Flask, render_template
在templates中写html模板,在app.py中调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TopView</title>
</head>
<body>
<h1>TopView<h1>
</body>
</html>
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/')
def hello_world(): # put application's code here
return render_template("index.html")
可以传参数到html中,html用{{ }}调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>博客详情</title>
</head>
<body>
<h1>你访问的博客详情是: {{ blog_id }}</h1>
<p>名字为: {{ name }}</p>
</body>
</html>
#可以传参数到html中
@app.route("/blog/<blog_id>")
def blog_detail(blog_id):
return render_template("blog_detail.html", blog_id = blog_id, name = "bigdata")
模板访问对象属性
可以在模板中访问对象,也可以访问字典,这里演示访问对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>TopView</title>
</head>
<body>
<h1>TopView</h1>
<div>{{ user.username }} / {{ user.email }}</div>
</body>
</html>
from flask import Flask, render_template
app = Flask(__name__)
class User:
def __init__(self, username, email):
self.username = username
self.email = email
#传入对象
@app.route('/')
def hello_world(): # put application's code here
user = User(username="xjt", email="213@123")
return render_template("index.html",user=user)
路由参数详解
写法
- string 接收任何没有斜杠 (‘/’) 的字符串
- int 接收整型
- float 接收浮点型
- path 接收路径, 可接受斜线 ( ’ / ’ )
- uuid 只接受uuid字符串 , 唯一码, 一种生成规则
- any 可以同时指定多种路径, 进行限定
string
可以不加string:xxx , flask默认值是string
@app.route('/string/<username>/')
def hello_world(username): # put application's code here
return username
int
提示不可以传int的时候,要用str()转成string
@app.route('/<int:id>/')
def hello_world(id): # put application's code here
print(id)
# return str(id)
return str(id)
float
@app.route('/<float:money>/')
def hello_world(money): # put application's code here
print(type(money))
# return str(id)
return str(money)
path
类似,也是转为str
uuid
@app.route('/uuid/')
def hello_world(): # put application's code here
import uuid
return str(uuid.uuid4())
any
@app.route('/any/<any(apple, orange, banana):fruit>/')
def hello_world(fruit): # put application's code here
print(type(fruit))
return str(fruit)
请求方法
默认支持GET, HEAD, OPTIONS, 如果想支持某一请求方式,需手动
methods: 请求方法
默认不支持POST
如果需要同时支持GET和POST, 就设置methods
@app.route("/methods/", methods=['GET', 'POST'])
def get_methods():
return "methods"
用爬虫测试
import requests
res = requests.post('http://127.0.0.1:5000/methods/')
print(res.text)
flask请求和响应
Request
用request需要导包
from flask import Flask,request
客户端向服务端发送的请求
@app.route("/request/", methods=['GET', 'POST'])
def get_request():
print(request) #<Request 'http://127.0.0.1:5000/request/' [GET]>
return "request"
重要属性
请求的参数
#GET请求的参数
#类字典对象
print(request.args) #ImmutableMultiDict([('name', 'lisi'), ('name', 'wangwu'), ('age', '23')])
print(request.args.get('name')) #这个用的多,值空返回NULL防止值为空报错,只会返回第一个匹配的 lisi
#POST请求的参数
#同上
print(request.form)
print(request.form.get('name'))
cookies
print(request.cookies) #ImmutableMultiDict([('name', 'hello')])
路径
#路径
print(request.path) #/request/
print(request.url) #http://127.0.0.1:5000/request/?name=lisi&name=wangwu&age=23
print(request.base_url) #http://127.0.0.1:5000/request/
print(request.host_url) #http://127.0.0.1:5000/
print(request.remote_addr) #127.0.0.1 客户端的ip
print(request.files) #文件内容
print(request.headers) #请求头
print(request.user_agent) # 用户代理, 包括浏览器和操作系统的信息, python-requests/2.31.0
响应
- 返回字符串
- 模板渲染(前后端不分离)
- 返回json数据(前后端分离)
- 自定义response对象
导入make_response或者Response
html = render_template('index.html')
#1
res = make_response(html, 200)
#2
res = Reponse(html)
return res
Redirect: 重定向
url_for()
函数用于构建指定函数的 URL。它把函数名称作为第 一个参数。它可以接受任意个关键字参数,每个关键字参数对应 URL 中的变量。
from flask import Flask, redirect, url_for
app = Flask(__name__)
@app.route("/to/")
def helloworld():
return "hello"
@app.route("/redirect/")
def get_request():
#重定向的几种方式
# return redirect("https://www.qq.com")
# return redirect("/to/")
#url_for(): 反向解析,通过视图函数名反过来找到路由
# url_for('蓝图名称.视图函数名')
ret1 = url_for('helloworld')
print('ret:' , ret1) #ret: /to/
return redirect(ret1)
#url_for传参
# ret2 = url_for('helloworld',name='wangwu')
# return redirect(ret2)
if __name__ == '__main__':
app.run(debug=True)
会话技术
Cookie
作用: 让服务器能够认识浏览器,常用于登录
流程:
- 浏览器:登录
- 服务器:验证用户名和密码,设置好cookie(和登录用户绑定), 返回给浏览器
- 浏览器:自动存储cookie到本地
- 下一次再请求会自动携带浏览器的cookie
- 服务器:取出cookie的值,判断是哪个用户在访问,返回对应用户的数据
- 浏览器:接收
设置cookie
获取cookie
删除cookie
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h2>首页</h2>
<hr>
{% if username %}
<p>
当前登录用户: {{ username }}
<a href="/logout/">注销</a>
</p>
{% else %}
<a href="/login/">登录</a>
{% endif %}
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>home</title>
</head>
<body>
<h2>首页</h2>
<hr>
<form action="/login/" method="post">
<p>
用户名: <input type="text" name="username">
</p>
<p>
密码: <input type="password" name="password">
</p>
<p>
<button>提交</button>
</p>
</form>
</body>
</html>
app.py 流程
import datetime
from flask import Flask, redirect, url_for,request, render_template
app = Flask(__name__)
@app.route("/")
@app.route('/home/')
def home():
# 4. 获取cookie
username = request.cookies.get('user')
return render_template('home.html', username = username)
@app.route("/login/", methods=['GET', 'POST'])
def login():
#GET: 访问登录页面
if request.method == 'GET':
return render_template('login.html')
#POST: 实现登录功能
elif request.method =='POST':
pass
# 1. 获取前端提交过来的数据
username = request.form.get('username')
password = request.form.get('password')
# 2. 模拟登录: 用户名和密码验证
if username == 'lisi' and password == '123':
#登录成功
response = redirect('/home/')
# 3. 设置cookie
# cookie不能用中文
# 过期时间
# max_age: 秒
# expires: 指定的datetime日期
# response.set_cookie('user', username, max_age=3600*24*7)
response.set_cookie('user', username,expires=datetime.datetime(2024, 7, 12))
return response
else:
return "用户名或密码错误"
@app.route("/logout/")
def logout():
response = redirect("/home/")
# 5. 删除cookie
response.delete_cookie('user')
return response
if __name__ == '__main__':
app.run(debug=True)
Session
服务器端会话技术,依赖于cookie
session也是全局对象
总体和cookie差不多
只需要改四个地方
- 设置
- 获取
- 删除
- 设置secret_key
import datetime
from flask import Flask, redirect, url_for,request, render_template,session
app = Flask(__name__)
#session配置
print(app.config)
app.config['SECRET_KEY'] = 'abc123'
@app.route("/")
@app.route('/home/')
def home():
# 获取session
username = session.get('user')
return render_template('home.html', username = username)
@app.route("/login/", methods=['GET', 'POST'])
def login():
#GET: 访问登录页面
if request.method == 'GET':
return render_template('login.html')
#POST: 实现登录功能
elif request.method =='POST':
pass
# 1. 获取前端提交过来的数据
username = request.form.get('username')
password = request.form.get('password')
# 2. 模拟登录: 用户名和密码验证
if username == 'lisi' and password == '123':
#登录成功
response = redirect('/home/')
#3. 设置session
session['user'] = username
return response
else:
return "用户名或密码错误"
@app.route("/logout/")
def logout():
response = redirect("/home/")
# 删除session
session.pop('user')
# session.clear() #慎用
return response
if __name__ == '__main__':
app.run(debug=True)
html和cookie一样,无修改
cookie和session的区别:
cookie:
- 在浏览器存储
- 安全性较低
- 可以减轻服务器压力
session
- 在服务器端存储
- 安全性高
- 对服务器要求较高
- 依赖cookie