Flask接收请求
flask 通过request方法来接收前端请求过来的参数,具体常用的方法:
方法 | 描述 |
args | get请求的方法 |
data | 原始的请求数据 |
form | 接收post请求方法的参数 |
files | 接收文件请求参数 |
method | 请求方式,加载页面的请求都是get请求 |
referer | 请求来源 |
host | 主机 |
host_url | 主机地址 |
以上数据存放在url或者请求头部。
表单请求
就是利用HTML的表单和组件向服务器发起请求,在过程当中需要对form标签设置以下参数
参数 | 描述 |
method | 请求方式,默认是GET |
action | 请求的地址,就是将数据提交到哪里,默认提交到当前路由 |
enctype | 用来表述请求数据不单单是字符 |
注意:form表单的元素必须有name标签,否者前端请求不发送数据。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form method="get" action="/index/">
<input type="text">
<button>搜索</button>
</form>
</body>
</html>
POST请求
post请求用于向服务器提交数据,flask视图函数默认只接受get请求数据,post数据需要设置,并且使用request.form接受post数据
@app.route("/add_page/",methods = ["GET","POST"])
def add_page():
if request.method == "POST":
#获取post提交的数据
data = request.form
p_name = data.get("p_name")
gender = data.get("gender")
age = data.get("age")
education = data.get("education")
department = data.get("department")
position = data.get("position")
#定义工号
number = Person.query.all()[-1].id+1
#定义工资
m = 5000 # 基本工资
m_1 = 1000 # 职级工资
if position == "部长":
m_1 = 1000 * 4
elif position == "经理":
m_1 = 1000 * 3
elif position == "组长":
m_1 = 1000 * 2
money = m + m_1
#保存数据
p = Person()
p.work_number = str(number).zfill(8)
p.p_name = p_name
p.gender = gender
p.age = age
p.education = education
p.department = department
p.position = position
p.money = money
p.save()
return render_template("add_page.html")
post数据需要在form标签上设置method属性
<form method="post">
<div>
<label>姓名:</label>
<input type="text" name="p_name">
</div>
<div>
<label>性别:</label>
<input type="radio" value="男" name="gender">男
<input type="radio" value="女" name="gender">女
</div>
<div>
<label>年龄</label>
<input type="number" name="age">
</div>
<div>
<label>学历</label>
<input type="text" name="education">
</div>
<div>
<label>部门</label>
<select name="department">
<option value="人事部">人事部</option>
<option value="人事部">财务部</option>
<option value="人事部">后勤部</option>
<option value="人事部">研发部</option>
<option value="人事部">销售部</option>
<option value="人事部">安保部</option>
<option value="人事部">市场部</option>
<option value="人事部">采购部</option>
</select>
</div>
<div>
<label>职位</label>
<select name="position">
<option value="部长">部长</option>
<option value="经理">经理</option>
<option value="组长">组长</option>
<option value="职员">职员</option>
</select>
</div>
<div>
<input type="submit" value="提交">
</div>
</form>
flask 表单文件提交
前端需要注意在form标签上添加enctype属性
<form method="post" enctype="multipart/form-data">
<div class="form-group">
<label class="control-label">标题:</label>
<input class="form-control" type="text" name="title" placeholder="标题">
</div>
<div class="form-group">
<label class="control-label">作者:</label>
<input class="form-control" type="text" name="author" placeholder="作者">
</div>
<div class="form-group">
<label class="control-label">内容:</label>
<textarea class="form-control ckeditor" name="content"></textarea>
</div>
<div class="form-group">
<label class="control-label">图片:</label>
<input type="file" name="picture">
</div>
<div class="form-group">
<button class="btn btn-primary btn-block">提交</button>
</div>
</form>
后端需要request.files接收数据,并且在保存图片的同时,将路径保存到数据库
@app.route("/add_news/",methods = ["GET","POST"])
def add_news():
if request.method == "POST":
data = request.form
title = data.get("title")
author = data.get("author")
content = data.get("content")
#保存图片
picture = request.files.get("picture")
#图片名称
filename = picture.filename
#图片保存路径
path = os.path.join(
os.path.dirname(
os.path.abspath(__file__)
),"static"
)
file_path = os.path.join("img",filename)
save_path = os.path.join(path,file_path)
picture.save(save_path) #保存
news = News()
news.title = title
news.author = author
news.content = content
news.picture = file_path
news.public_time = datetime.datetime.now()
news.save()
return redirect8 #跳转
return render_template("add_news.html")
ajax技术
常规web请求,总是会刷新页面,这个事情不是很好。
以用户名 重复校验为例子
前端可以通过js或者jq构建ajax结构
$.ajax({
url: "/has_user/?username="+value, //请求的地址 类似form的action
type: "get", //请求的方法 类似form表单的method
data: "", // 类似input的数据
success: function (data) {
console.log(data);
$("#error").text(data["d"])
}, //请求成功执行的函数,会接收返回的数据
error: function (error) {
console.log(data)
} //请求失败执行的函数,会接收返回的数据
})
注意ajax通常不会和页面共用一个视图,因为标准ajax数据返回格式是json。
@app.route("/demo/")
def ajax_demo():
"""
返回页面
:return:
"""
return render_template("ajax_demo.html")
from flask import jsonify #json
@app.route("/has_user/")
def has_user():
"""
处理ajax,数据返回到请求ajax地址的js当中
:return:
"""
user = request.args.get("username")
p = Person.query.filter(Person.username == user).first()
result = {"l":[1,2,3]}
if p:
result["d"] = "用户名已经存在"
else:
result["d"] = "用户名可以使用"
return jsonify(result)
Cookie和Session
Cookie(曲奇)机制:在用户请求服务器的时候,服务器下发身份校验到用户本地,之后用户携带这个校验数据请求服务器其他地方,服务器通过这个校验数据识别用户身份,这种机制就是cookie机制。
HTTP的每次请求是独立的,和上一次,下一次请求没有关系,所以需要采用上述的cookie机制来进行身份校验。
由于cookie保存在本地,就会出现以下情况:
1、可以被拒绝
2、可以被仿照
3、可以被劫持
使用cookie步骤:
1、下发cookie(生成cookie)
cookie必须通过response对象进行下发,render_template返回的是一个字符串对象,需要使用make_response对象进行转换
response.set_cookie 可以设置cookie
参数 | 描述 |
key | cookie的键 |
value | cookie的值 |
max_age | 寿命,有效期,秒 60*15 默认关闭浏览器,cookie过期 |
expires | 过期时间,具体的时间节点,和max_age冲突 |
path | cookie起作用的范围 默认是 /,也可以设置其他路由 |
domain | 起作用的网站,或者域名 www.baidu.com |
secure | 是否采用用安全的cookie传输方式 |
httponly | 只使用http协议,不使用https协议 |
samesite | 起作用的url |
from flask import make_response
@app.route("/cookieExm/")
def cookieExm():
response = make_response(render_template("empty.html"))
response.set_cookie("name","laobian")
return response
2、携带cookie请求,浏览器会自动安装cookie设置携带cookie去请求。
3、校验cookie
获取
比对
@app.route("/getcookie/")
def getcookie():
name = request.cookies.get("hello")
if name and name == "laobian":
response = make_response("laobian")
else:
response = make_response("校验失败")
return response
案例:
登录案例
密码加密
import hashlib
def setPassWord(password):
md5 = hashlib.md5()
md5.update(password.encode())
return md5.hexdigest()
注册
@app.route("/register/",methods=["GET","POST"])
def register():
"""
密码需要加密
"""
if request.method == "POST":
#接收post数据
username = request.form.get("username")
password = request.form.get("password")
#校验用户名是否重复
user = Person.query.filter_by(username = username).first()
if not user:
p = Person()
p.username = username
#密码加密
p.password = setPassWord(password)
#保存数据
p.save()
#跳转到登录页面
return redirect("/login/")
return render_template("register.html")
登录
@app.route("/login/",methods=["GET","POST"])
def login():
if request.method == "POST":
# 接收post数据
username = request.form.get("username")
password = request.form.get("password")
password = setPassWord(password) #对请求密码加密
user = Person.query.filter_by(username = username,password = password).first() #校验用户名和密码
if user:
#设置cookie
respone = redirect("/index/") #本身就是response对象
respone.set_cookie("username",user.username) #设置cookie
return respone #返回响应
return render_template("login.html")
首页
登录校验
from functools import wraps
def is_login(fun):
@wraps(fun)
def inner(*args,**kwargs):
username = request.cookies.get("username")
if username and Person.query.filter_by(username=username).first():
return fun(*args,**kwargs) #返回被装饰函数的功能
else:
return redirect("/login/") #否者返回登录页面
return inner
退出
@app.route("/logout/")
def logout():
"""
退出就是删除cookie的过程
:return:
"""
response = redirect("/login/")
response.delete_cookie("username") #删除客户浏览器本地cookie
return response