文章目录
Web开发框架----Flask
一、架构简介
1.什么是Flask?
我们通过浏览器去访问网站时的流程:
一般浏览器会先把请求抛给Nginx,Nginx在抛给后台服务器(阿帕奇),用户接触的是Nginx。
之前说到,http和浏览器进行交流的时候使用的是https协议,但 Flask和请求交流的时候 之间没有协议,中间有个uWSGI
- Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP 服务
- uWSGI是一个Web服务器(和后端交流),它实现了WSGI协议(与Flask等框架交流)、uwsgi、http(与Nginx交流)等协议。
- Framework即架构,它是一个语言开发软件,提供了软件开发的框架,使开发更具工程性、简便
性和稳定性。
Flask是一个Web框架,就是提供一个工具,库和技术来允许你构建一个Web应用程序.这个Web应用程序
可以是一些Web页面,博客, wiki ,基于 Web 的日历应用或商业网站。
Flask依赖模块:(flask为什么是微内核框架?)
web服务网关接口(Python Web Server Gateway Interface,缩写为WSGI
只提供以下核心功能
- Werkzeug 一个WSGI工具包, 是为python语言定义的web服务器和web应用程序或框架之间的一
种简单而通用的借口,其他语言也有类似的接口) - jinja2模板引擎
Flask的优势
Flask属于微框架( micro-framework )这一类别,微架构通常是很小的不依赖外部库的框架.
- 框架很轻量
- 更新时依赖小
- 专注于安全方面的bug
2.Flask第一个网站
两个名词:
路由:
@app.route() #访问的路径
视图函数:
def 函数名() #给用户返回的页面信息
Flask是网页框架,主要可以在编程中实现网页显示,和网页交互等功能,实现Web程序开发。
from flask import Flask
app = Flask(__name__) #实例化一个Flask
# 实现首页: http://172.25.254.197:9999/
@app.route('/') # 路由
def index(): # 视图函数, 一定不能重复;
return '这是网站的首页'
@app.route('/login/')
def login():
return "正在登录......"
@app.route('/logout/')
def logout():
return "正在登出......"
if __name__ == '__main__':
# 运行Flask项目, 默认ip和端口是127.0.0.1:5000
# 如何特色化指定? host='0.0.0.0' 开放本机的所有IP port=5000 端口必须是整形数
# debug=True: 是否开启调试模式, 测试环境中开启, 生产环境一定要关闭.
app.run(host='0.0.0.0', port=9999, debug=True)
linux中可以用0.0.0.0:9998直接访问
windows中用127.0.0.1:9998或者192.168.1.109:9998访问(本机IP+端口号)
理解:
- 这里的
0.0.0.0
代表是IP的每一位是任意的,其实就是绑定电脑上的所有IP,如果本机有两个IP,就通过IP1:端口号
或者IP2:端口号
是可以访问的。 - 绑定了ip才能共享到网络,让其他主机访问。那么绑定
0.0.0.0
代表共享当前主机所有的IP地址。 - 在Linux系统中,直接使用
0.0.0.0
是可以自动获取的,但是在windows中输入0.0.0.0不能自动获取,要手动输入本机的IP:127.0.0.1
或者192.168.1.109
- 查询本机有几个IP通过命令
ipconfig
查询(Windows系统),ifconfig
查询(Linux系统)
127.0.0.1:回环地址IP,就是自己的电脑的一个进程和自己电脑上的某一个进程进行通信的时候,为了速度更快,他就用这个回环地址进行通信。也就是说,每一台电脑上都会有一个回环地址IP,就叫127.0.0.1,就是自己访问自己用这个IP是可以的。
3.路由和变量规则
"""
# 1.路由中的变量规则
有时候需要接收URL中的参数变量,可以把参数标记为一个变量<变量名>,这个部分将会作为命名参数传递给函数。
同时还可以限制参数变量的类型<类型:变量名>。
# 2. 数据类型一共有三种:int, float, path
类型 描述
int 接受整数
float 同 int ,但是接受浮点数
path 和默认的相似,但也接受斜线
# 3. 范例1:
http://www.csdn.org/12000
http://www.csdn.org/12001
http://www.csdn.org/12002
http://www.csdn.org/12003
# 4.范例2-动态路由:
http://www.csdn.org/<userid>
"""
from flask import Flask, request
app = Flask(__name__)
@app.route('/<int:userid>/')
def userinfo(userid):
return "正在查看用户%s的详细博客........" %(userid)
@app.route('/welcome/<string:username>')
def welcome(username):
return "欢迎访问%s用户的主页" %(username)
"""
https://movie.douban.com/top250?start=25&filter=
"""
@app.route('/top250')
def top250():
users = ['user%s' %(i) for i in range(100)]
# request存储用户请求页面的所有头部信息
print("客户端的用户代理: ", request.user_agent) # Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Firefox/45.0
print("请求页面的头部信息: ", request.headers)
print("客户端的IP:", request.remote_addr) # 127.0.0.1
print("客户端请求的参数详细信息: ", request.args) # ImmutableMultiDict([('start', '25'), ('user', 'westos')])
print("客户端HTTP请求方法: ", request.method) # GET
# 获取用户请求的url地址里面可以对应的value值;
start = int(request.args.get('start')) # '25'
user = request.args.get('user') # 'westos'
# return 'top 250 显示数据开始:%s条 用户名: %s' %(start, user)
import json
return json.dumps(users[start:start+10])
if __name__ == '__main__':
app.run()
在浏览器中访问路由
查看运行结果:
遇到问题:
在浏览器上访问 http://127.0.0.1:5000/ 报错404
解决:
因为路由和视图函数没有处理首页的内容,这里没有视图函数 即:
@app.route('/') # 路由
def index(): # 视图函数, 一定不能重复;
return '这是网站的首页'
后面要加上处理的内容 http://127.0.0.1:5000/welcome/daliu
即可:
二、http请求方法的实现
1.http常见的请求方式:get和post的区别?
method是http请求的方法,常见的http请求方法有get,post,delete。
get和post的区别?
1). url可见性:
get,参数url可见;
post,url参数不可见
2). 数据传输上:
get,通过拼接url进行传递参数;
post,通过body体传输参数
3). 缓存性:
get请求是可以缓存的
post请求不可以缓存
4). 后退页面的反应
get请求页面后退时,不产生影响
post请求页面后退时,会重新提交请求
5). 传输数据的大小
get一般传输数据大小不超过2k-4k(根据浏览器不同,限制不一样,但相差不大)
post请求传输数据可以无限大。
6). 安全性: 原则上post肯定要比get安全。
2.模版渲染
通俗理解:先有一个http的模板,模板中有一些空,这些空等待用户的返回信息来填充,返回一个真实的html给用户
hello {
{ name }}
name = westos hello westos
Flask和Django一样都配备了Jinja2模版引擎,可以使用render_template()方法来渲染模版。
3.重定向和错误(redirect,error)
使用redirect()函数把用户重定向到其他地方。 ‘/bbs’ —> ‘/login’
使用abort()函数,放弃请求并返回错误代码。 # HTTP状态码: 404(4开头的是客户端错误), 200, 304, 500(5开头的是服务端错误)
4.get方法实现 登陆验证
实现流程: 运行主函数后,用户在浏览器中访问'/login/'
路由,即 执行def login():
函数,返回login.html
页面,在login.html
页面输入用户名和密码并点击登陆按钮,表单把信息提交给/login2/
路由,在主函数页面执行def login2():
函数,如果登录成功则进入主页,如果登录失败,重定向到登录界面重新登录;
py文件:
from flask import Flask, render_template, request, redirect
app = Flask(__name__)
@app.route('/')
def index():
return "<h1>主页</h1>"
@app.route('/login/')
def login():
"""
一般情况, 不会直接把html文件内容直接返回;
而是将html文件保存到当前的templates目录中;
1). 通过render_template方法调用;
2). 默认情况下,Flask 在程序文件夹中的 templates 子文件夹中寻找模板。
"""
return render_template('login.html')
@app.route('/login2/')
def login2():
# 获取用户输入的用户名
username = request.args.get('username', None)
password = request.args.get('password', None)
# 逻辑处理, 用来判断用户和密码是否正确;
if username == 'root' and password == 'redhat':
# 重定向到指定路由;
# 如果登录成功, 进入主页.
return redirect('/')
# return "登录成功"
else:
# return "登录失败"
# 如果登录失败, 重定向到登录界面重新登录;
return redirect('/login/')
if __name__ == '__main__':
app.run()
templates目录中的login.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户登录</h1>
<form action="/login2/" method="GET">
<input type="text" name="username" placeholder="username"><br/>
<input type="password" name="password" placeholder="password"><br/>
<input type="submit" value="登录" >
</form>
</body>
</html>
输入用户名和密码:
root
redhat
登陆
5.post方法实现登录验证
用get方法会显示密码和用户名,不安全,下面用post方法实现
难点: post请求提交的数据如何获取? request.form
难点: get请求提交的数据如何获取? request.args
py文件:
from flask import Flask, request, render_template, redirect, abort
app = Flask(__name__)
@app.route('/')
def index():
return "这是主页"
# 默认路由只支持get方法, 如何指定接受post方法?
@app.route('/login/', methods=['GET', 'POST'])
def login():
"""
1. 用户访问网址: http://xxxx/login, 返回登录的html页面;
方法method: GET
2. 用户在表单中填写信息,
<form action="/login/" method="POST">
3. 执行post提交的逻辑;
:return:
"""
if request.method == 'POST':
# 难点: post请求提交的数据如何获取? request.form
# 难点: get请求提交的数据如何获取? request.args
print(request.form)
username = request.form.get('username')
password = request.form.get('password')
# 如果用户名和密码正确, 跳转到主页;
if username == 'root' and password == 'redhat':
return redirect('/')
# 如果登录不正确, 则警告红色信息;还是在登录页面;并且传递变量errMessages
else:
# 可以给html传递变量
return render_template('login_post.html',
errMessages="用户名或者密码错误"
)
else:
# abort(500)
return render_template('login_post.html')
if __name__ == '__main__':
app.run()
templates目录中的login_post.html文件:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>用户登录</h1>
<form action="/login/" method="POST">
<input type="text" name="username" placeholder="username"><br/>
<input type="password" name="password" placeholder="password"><br/>
<input type="submit" value="登录" >
</form>
{
#errMessages用来占位的 #}
<p style="color: red">{
{
errMessages}}