Python——Flask基础学习
摘要
由于公司的大家都是python来实现的项目的构建,因此本文也将来学习相关的python的相关的学习。本章将讲解的是Flask框架的学习。
Flask是由python实现的一个web微框架,让我们可以使用Python语言快速实现一个网站或Web服务。而且有对应的python3及python2版本。
1、安装Flask
pip install flask
2、目录结构
flask-demo/├ run.py # 应用启动程序├ config.py # 环境配置├ requirements.txt # 列出应用程序依赖的所有Python包├ tests/ # 测试代码包│ ├ __init__.py │ └ test_*.py # 测试用例└ myapp/├ admin/ # 蓝图目录├ static/│ ├ css/ # css文件目录│ ├ img/ # 图片文件目录│ └ js/ # js文件目录├ templates/ # 模板文件目录├ __init__.py ├ forms.py # 存放所有表单,如果多,将其变为一个包├ models.py # 存放所有数据模型,如果多,将其变为一个包└ views.py # 存放所有视图函数,如果多,将其变为一个包
3、开始 Hello world
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():return 'Hello World'
if __name__ == '__main__':app.debug = True # 设置调试模式,生产模式的时候要关掉debugapp.run()
这是flask框架制作的一个最小的应用。使用python运行后访问localhost:5000就能看到网页显示Hello world。这里首先引入了Flask类,然后给这个类创建了一个实例,name代表这个模块的名字。因为这个模块是直接被运行的所以此时name的值是main。然后用route()这个修饰器定义了一个路由,告诉flask如何访问该函数。最后用run()函数使这个应用在服务器上运行起来。
4、模板
Flask的模板功能是基于Jinja2模板引擎实现的。让我们来实现一个例子吧。创建一个新的Flask运行文件(你应该不会忘了怎么写吧),代码如下:
from flask import Flaskfrom flask import render_templateapp = Flask(__name__)@app.route('/hello')@app.route('/hello/<name>')def hello(name=None):return render_template('hello.html', name=name)if __name__ == '__main__':app.run(host='0.0.0.0', debug=True)
这段代码”hello()”函数并不是直接返回字符串,而是调用了”render_template()”方法来渲染模板。方法的第一个参数”hello.html”指向你想渲染的模板名称,第二个参数”name”是你要传到模板去的变量,变量可以传多个。
那么这个模板”hello.html”在哪儿呢,变量参数又该怎么用呢?接下来我们创建模板文件。在当前目录下,创建一个子目录”templates”(注意,一定要使用这个名字)。然后在”templates”目录下创建文件”hello.html”,内容如下:
<!doctype html><title>Hello Sample</title>{% if name %}<h1>Hello {{ name }}!</h1>{% else %}<h1>Hello World!</h1>{% endif %}
这段代码是不是很像HTML?接触过其他模板引擎的朋友们肯定立马秒懂了这段代码。它就是一个HTML模板,根据”name”变量的值,显示不同的内容。变量或表达式由”{{ }}”修饰,而控制语句由”{% %}”修饰,其他的代码,就是我们常见的HTML。
让我们打开浏览器,输入”http://localhost:5000/hello/man”,页面上即显示大标题”Hello man!”。我们再看下页面源代码
<!doctype html><title>Hello from Flask</title><h1>Hello man!</h1>
果然,模板代码进入了”Hello {{ name }}!”分支,而且变量”{{ name }}”被替换为了”man”。Jinja2的模板引擎还有更多强大的功能,包括for循环,过滤器等。模板里也可以直接访问内置对象如request, session等。对于Jinja2的细节,感兴趣的朋友们可以自己去查查。
5、模板继承
一般我们的网站虽然页面多,但是很多部分是重用的,比如页首,页脚,导航栏之类的。对于每个页面,都要写这些代码,很麻烦。Flask的Jinja2模板支持模板继承功能,省去了这些重复代码。让我们基于上面的例子,在”templates”目录下,创建一个名为”layout.html”的模板:
<!doctype html><title>Hello Sample</title><link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}"><div class="page">{% block body %}{% endblock %}</div>
再修改之前的”hello.html”,把原来的代码定义在”block body”中,并在代码一开始”继承”上面的”layout.html”:
{% extends "layout.html" %}{% block body %}{% if name %}<h1>Hello {{ name }}!</h1>{% else %}<h1>Hello World!</h1>{% endif %}{% endblock %}
打开浏览器,再看下”http://localhost:5000/hello/man”页面的源码。
<!doctype html><title>Hello Sample</title><link rel="stylesheet" type="text/css" href="/static/style.css"><div class="page"><h1>Hello man!</h1></div>
你会发现,虽然”render_template()”加载了”hello.html”模板,但是”layout.html”的内容也一起被加载了。而且”hello.html”中的内容被放置在”layout.html”中”{% block body %}”的位置上。形象的说,就是”hello.html”继承了”layout.html”。
HTML自动转义
@app.route('/')def index():return '<div>Hello %s</div>' % '<em>Flask</em>'
打开页面,你会看到”Hello Flask”字样,而且”Flask”是斜体的,因为我们加了”em”标签。但有时我们并不想让这些HTML标签自动转义,特别是传递表单参数时,很容易导致HTML注入的漏洞。我们把上面的代码改下,引入”Markup”类:
from flask import Flask, Markupapp = Flask(__name__)@app.route('/')def index():return Markup('<div>Hello %s</div>') % '<em>Flask</em>'
再次打开页面,”em”标签显示在页面上了。Markup还有很多方法,比如”escape()”呈现HTML标签, “striptags()”去除HTML标签。这里就不一一列举了。
Request 对象
from flask import Flask,url_for,request,render_template@app.route('/login', methods=['POST', 'GET'])
def login():if request.method == 'POST':if request.form['user'] == 'admin':return 'Admin login successfully!'else:return 'No such user!'title = request.args.get('title', 'Default')return render_template('login.html', title=title)
if __name__ == "__main__":app.run(debug=True)
简单解释下,request中”method”变量可以获取当前请求的方法,即”GET”, “POST”, “DELETE”, “PUT”等;”form”变量是一个字典,可以获取Post请求表单中的内容,在上例中,如果提交的表单中不存在”user”项,则会返回一个”KeyError”,你可以不捕获,页面会返回400错误(想避免抛出这”KeyError”,你可以用request.form.get(“user”)来替代)。而”request.args.get()”方法则可以获取Get请求URL中的参数,该函数的第二个参数是默认值,当URL参数不存在时,则返回默认值。
在当前目录下,创建一个子目录”templates”(注意,一定要使用这个名字)。然后在”templates”目录下,添加layout.html
<!doctype html>
<title>Hello Sample</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
<div class="page">{% block body %}{% endblock %}
</div>
{% extends "layout.html" %}
{% block body %}
<form name="login" action="/login" method="post">Hello {{ title }}, please login by:<input type="text" name="user" />
</form>
{% endblock %}
会话session
会话可以用来保存当前请求的一些状态,以便于在请求之前共享信息。
from flask import Flask,url_for,request,render_template,redirect,session
@app.route('/login', methods=['POST', 'GET'])
def login():if request.method == 'POST':if request.form['user'] == 'admin':session['user'] = request.form['user']return 'Admin login successfully!'else:return 'No such user!'if 'user' in session:return 'Hello %s!' % session['user']else:title = request.args.get('title', 'Default')return render_template('login.html', title=title)
@app.route('/logout')
def logout():session.pop('user', None)return redirect(url_for('login'))app.secret_key = '123456'
if __name__ == "__main__":app.run(debug=True)
你可以看到,”admin”登陆成功后,再打开”login”页面就不会出现表单了。然后打开logout页面可以登出。session对象的操作就跟一个字典一样。特别提醒,使用session时一定要设置一个密钥”app.secret_key”,如上例。不然你会得到一个运行时错误,内容大致是”RuntimeError: the session is unavailable because no secret key was set”。密钥要尽量复杂,最好使用一个随机数,这样不会有重复,上面的例子不是一个好密钥。
构建响应
在之前的例子中,请求的响应我们都是直接返回字符串内容,或者通过模板来构建响应内容然后返回。其实我们也可以先构建响应对象,设置一些参数(比如响应头)后,再将其返回。修改下上例中的Get请求部分:
from flask import Flask,url_for,request,render_template,redirect,session,make_response@app.route('/login', methods=['POST', 'GET'])
def login():if request.method == 'POST':...if 'user' in session:...else:title = request.args.get('title', 'Default')response = make_response(render_template('login.html', title=title), 200)response.headers['key'] = 'value'return response
if __name__ == "__main__":app.run(debug=True)
打开浏览器调试,在Get请求用户未登录状态下,你会看到响应头中有一个”key”项。”make_response”方法就是用来构建response对象的,第二个参数代表响应状态码,缺省就是200。
Cookie的使用
提到了Session,当然也要介绍Cookie喽,毕竟没有Cookie,Session就根本没法用(不知道为什么?查查去)。Flask中使用Cookie也很简单:
from flask import Flask,url_for,request,render_template,redirect,session,make_response
import time
@app.route('/login', methods=['POST', 'GET'])
def login():response = Noneif request.method == 'POST':if request.form['user'] == 'admin':session['user'] = request.form['user']response = make_response('Admin login successfully!')response.set_cookie('login_time', time.strftime('%Y-%m-%d %H:%M:%S'))...else:if 'user' in session:login_time = request.cookies.get('login_time')response = make_response('Hello %s, you logged in on %s' % (session['user'], login_time))...return response
app.secret_key = '123456'
if __name__ == "__main__":app.run(debug=True)
这次我们引入了”time”模块来获取当前系统时间。我们在返回响应时,通过”response.set_cookie()”函数,来设置Cookie项,之后这个项值会被保存在浏览器中。这个函数的第三个参数(max_age)可以设置该Cookie项的有效期,单位是秒,不设的话,在浏览器关闭后,该Cookie项即失效。在请求中,”request.cookies”对象就是一个保存了浏览器Cookie的字典,使用其”get()”函数就可以获取相应的键值。
错误处理
使用”abort()”函数可以直接退出请求,返回错误代码:
rom flask import Flask,abortapp = Flask(__name__)
@app.route('/error')
def error():abort(404)if __name__ == "__main__":app.run(debug=True)
上例会显示浏览器的404错误页面。有时候,我们想要在遇到特定错误代码时做些事情,或者重写错误页面,可以用下面的方法:
rom flask import Flask,abortapp = Flask(__name__)@app.errorhandler(404)
def page_not_found(error):return render_template('404.html'), 404
if __name__ == "__main__":app.run(debug=True)
不过,在实际开发过程中,我们并不会经常使用”abort()”来退出,常用的错误处理方法一般都是异常的抛出或捕获。装饰器”@app.errorhandler()”除了可以注册错误代码外,还可以注册指定的异常类型。让我们来自定义一个异常:
class InvalidUsage(Exception):status_code = 400def __init__(self, message, status_code=400):Exception.__init__(self)self.message = messageself.status_code = status_code@app.errorhandler(InvalidUsage)
def invalid_usage(error):response = make_response(error.message)response.status_code = error.status_codereturn response
@app.route('/exception')
def exception():raise InvalidUsage('No privilege to access the resource', status_code=403)
if __name__ == "__main__":app.run(debug=True)
我们在上面的代码中定义了一个异常”InvalidUsage”,同时我们通过装饰器”@app.errorhandler()”修饰了函数”invalid_usage()”,装饰器中注册了我们刚定义的异常类。这也就意味着,一但遇到”InvalidUsage”异常被抛出,这个”invalid_usage()”函数就会被调用。
url重定向
Flask的URL规则是基于Werkzeug的路由模块。模块背后的思想是基于 Apache 以及更早的 HTTP 服务器主张的先例,保证优雅且唯一的 URL。
@app.route('/projects/')
def projects():return 'The project page'@app.route('/about')
def about():return 'The about page'
访问第一个路由不带/时,Flask会自动重定向到正确地址。访问第二个路由时末尾带上/后Flask会直接报404 NOT FOUND错误。
重定向”redirect()”函数的使用在上面例子中已有出现。作用就是当客户端浏览某个网址时,将其导向到另一个网址。常见的例子,比如用户在未登录时浏览某个需授权的页面,我们将其重定向到登录页要求其登录先。
from flask import session, redirect@app.route('/')
def index():if 'user' in session:return 'Hello %s!' % session['user']else:return redirect(url_for('login'), 302)
“redirect()”的第二个参数时HTTP状态码,可取的值有301, 302, 303, 305和307,默认即302(为什么没有304?留给大家去思考)。
1** : 信息,服务器收到请求,需要请求者继续执行操作2** : 成功,操作被成功接收并处理3** : 重定向,需要进一步的操作以完成请求4** :客户端错误,请求包含语法错误或无法完成请求5** :服务器错误,服务器在处理请求的过程中发生了错误
200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)204 NO CONTENT - [DELETE]:用户删除数据成功。400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,
该操作是幂等的。401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,
该操作是幂等的。406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。400 :请求参数错误 缺少参数,或者格式不匹配
401 :要求用户的身份认证,未授权
403 :访问受限,授权过期
404 :资源,服务未找到
405 :不允许http方法
Python——Flask基础学习相关推荐
- 第10期:Python零基础学习路线
大家好,我是你们的老朋友老王随聊,今天和大家讨论的话题--Python零基础应该怎么学? 通过这段时间和群里同学们交流,发现很多大学生甚至职场小白对Python学习路线不是很清晰,所以我花了一些时间给 ...
- Day2:python爬虫基础学习(大嘘)
Day2:python爬虫基础学习(大嘘)) 教材&参考: 学习过程 Sublime配置教程 下载&安装 语言(设置中文) 设置字体/配色 配置Python环境 使用python官方编 ...
- 软件测试Python编程基础学习分享
#博学谷IT学习技术支持# 目录 一.前言 二.python基础 2.1print函数的简单使用 2.2注释 2.2.1单行注释 2.2.2多行注释 2.3Python代码中三种波浪线和 PEP8 2 ...
- 1 python编程基础学习
1 python编程基础学习 1. 程序 2 python简介(了解) 3 python的开发环境的搭建 4 第一个python程序 4.1 常用的dos命令 4.2 交互式 4.3 使用pychar ...
- python pyramid基础学习二
python pyramid基础学习二 1.前言 前面我们使用了基础命令创建pyramid项目,并运行了Hello word,万事开头难,我们知道了开发pyramid项目需要一个env文件夹,里面包 ...
- Python Flask教程学习02
书接上文Python Flask教程学习01 文章目录 Flask 教程 Flask 会话 Flask 消息闪现 Flask 文件上传 Flask 扩展/寻找扩展 Flask 教程 Flask 会话 ...
- Python Flask教程学习03
书接上文Python Flask教程学习02 文章目录 Flask 教程 Flask 邮件(Flask-Mail) Flask Mysql及Flask SQLAlchemy 创建数据表 插入数据 查询 ...
- Python Flask基础教程(入门)
操作系统:Windows Python:3.5 欢迎加入学习交流QQ群:657341423 参考资料:请点击 安装:pip install flask即可 一个简单的Flask from flask ...
- python语法基础学习-Python基础语法精心总结!看完都知道的可以往下继续学习了...
原标题:Python基础语法精心总结!看完都知道的可以往下继续学习了 这应该是最详细的Python入门基础语法总结! 定义变量,使用变量 1. input 用户自己输入值 2. print 打印值 可 ...
最新文章
- 【11/11】模拟赛
- Tomcat 配置 项目 到tomcat目录外面 和 域名绑定访问(api接口、前端网站、后台管理网站)...
- 简易排水简车的制作 TurnipBit 系列教程
- pandas数据分析选则接近数值的最接优方案
- 物体检测 | 29篇顶会(刊)论文集
- C++新特性探究(十八):智能指针
- mysql+分页脚本_MySql实现分页查询的SQL
- python我想对你说_python学习22天----模块、包
- head 标签里有什么?
- 六位数字密码锁设计(数字电路,proteus仿真)
- 贝尔商道赚钱思维36道第09道:今之赚大钱者
- revel MySQL_Revel 教程
- Python分析《武林外传》 -----转载
- 罗克韦尔PLC程序,水处理自动化最高程序
- html input datetime格式化及后端接收
- Appium+python自动化3-启动淘宝app(转)
- nvm alias default [版本]不生效解决办法
- Poly2Tri介绍
- Kafka分区副本分配规则
- linux克隆tf卡中的内容,TF/SD内存卡数据克隆怎样做图文详细教程