摘要

由于公司的大家都是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基础学习相关推荐

  1. 第10期:Python零基础学习路线

    大家好,我是你们的老朋友老王随聊,今天和大家讨论的话题--Python零基础应该怎么学? 通过这段时间和群里同学们交流,发现很多大学生甚至职场小白对Python学习路线不是很清晰,所以我花了一些时间给 ...

  2. Day2:python爬虫基础学习(大嘘)

    Day2:python爬虫基础学习(大嘘)) 教材&参考: 学习过程 Sublime配置教程 下载&安装 语言(设置中文) 设置字体/配色 配置Python环境 使用python官方编 ...

  3. 软件测试Python编程基础学习分享

    #博学谷IT学习技术支持# 目录 一.前言 二.python基础 2.1print函数的简单使用 2.2注释 2.2.1单行注释 2.2.2多行注释 2.3Python代码中三种波浪线和 PEP8 2 ...

  4. 1 python编程基础学习

    1 python编程基础学习 1. 程序 2 python简介(了解) 3 python的开发环境的搭建 4 第一个python程序 4.1 常用的dos命令 4.2 交互式 4.3 使用pychar ...

  5. python pyramid基础学习二

    python pyramid基础学习二 1.前言 前面我们使用了基础命令创建pyramid项目,并运行了Hello word,万事开头难,我们知道了开发pyramid项目需要一个env文件夹,里面包 ...

  6. Python Flask教程学习02

    书接上文Python Flask教程学习01 文章目录 Flask 教程 Flask 会话 Flask 消息闪现 Flask 文件上传 Flask 扩展/寻找扩展 Flask 教程 Flask 会话 ...

  7. Python Flask教程学习03

    书接上文Python Flask教程学习02 文章目录 Flask 教程 Flask 邮件(Flask-Mail) Flask Mysql及Flask SQLAlchemy 创建数据表 插入数据 查询 ...

  8. Python Flask基础教程(入门)

    操作系统:Windows Python:3.5 欢迎加入学习交流QQ群:657341423 参考资料:请点击 安装:pip install flask即可 一个简单的Flask from flask ...

  9. python语法基础学习-Python基础语法精心总结!看完都知道的可以往下继续学习了...

    原标题:Python基础语法精心总结!看完都知道的可以往下继续学习了 这应该是最详细的Python入门基础语法总结! 定义变量,使用变量 1. input 用户自己输入值 2. print 打印值 可 ...

最新文章

  1. 【11/11】模拟赛
  2. Tomcat 配置 项目 到tomcat目录外面 和 域名绑定访问(api接口、前端网站、后台管理网站)...
  3. 简易排水简车的制作 TurnipBit 系列教程
  4. pandas数据分析选则接近数值的最接优方案
  5. 物体检测 | 29篇顶会(刊)论文集
  6. C++新特性探究(十八):智能指针
  7. mysql+分页脚本_MySql实现分页查询的SQL
  8. python我想对你说_python学习22天----模块、包
  9. head 标签里有什么?
  10. 六位数字密码锁设计(数字电路,proteus仿真)
  11. 贝尔商道赚钱思维36道第09道:今之赚大钱者
  12. revel MySQL_Revel 教程
  13. Python分析《武林外传》 -----转载
  14. 罗克韦尔PLC程序,水处理自动化最高程序
  15. html input datetime格式化及后端接收
  16. Appium+python自动化3-启动淘宝app(转)
  17. nvm alias default [版本]不生效解决办法
  18. Poly2Tri介绍
  19. Kafka分区副本分配规则
  20. linux克隆tf卡中的内容,TF/SD内存卡数据克隆怎样做图文详细教程

热门文章

  1. 需求DNA检测:如何判断一个功能是否值得做
  2. 如何让自己像打王者荣耀一样发了疯、拼了命、石乐志的学习?(转载)
  3. 提高商品曝光率增加销量,从这几点做起
  4. JLINK SW接线方式
  5. 基于 xterm + websocket + vue 实现网页版终端 terminal
  6. 如何实行反编译,将.class文件转化为.java文件
  7. Android图文混排(仿QQ空间评论)
  8. Redis之父Antirez谈副业与主业
  9. 计算机组成与维修心得,浅谈计算机组成与维护论文
  10. 出于对Java入门学习的考虑从Java基础出发