Python使用Web框架Flask开发项目

目录
  • 一、简介
  • 二、安装
  • 三、从 Hello World 开始
    • 3.1 Hello World
    • 3.2 修改Flask的配置
    • 3.3 调试模式
    • 3.4 绑定IP和端口
    • 3.5 本节源码
  • 四、获取 URL 参数
    • 4.1 建立Flask项目
    • 4.2 列出所有的url参数
    • 4.3 获取某个指定的参数
    • 4.4 如何处理多值
    • 4.5 本节源码
  • 五、获取POST方法传送的数据
    • 5.1 建立Flask项目
    • 5.2 查看POST数据内容
    • 5.3 解析POST数据
    • 5.4 本节源码
  • 六、处理和响应JSON数据
    • 6.1 建立Flask项目
    • 6.2 处理JSON格式的请求数据
    • 6.3 响应JSON-方案1
    • 6.4 响应JSON-方案2
    • 6.5 本节源码
  • 七、上传文件
    • 7.1 建立Flask项目
    • 7.2 上传文件
    • 7.3 本节源码
  • 八、Restful URL
    • 8.1 建立Flask项目
    • 8.2 编写代码
    • 8.3 转换类型
    • 8.4 一个有趣的用法
    • 8.5 编写转换器
    • 8.6 本节源码
  • 九、使用url_for生成链接
    • 9.1 建立Flask项目
    • 9.2 编写代码
    • 9.3 本节源码
  • 十、使用redirect重定向网址
    • 10.1 建立Flask项目
    • 10.2 编写代码
    • 10.3 本节源码
  • 十一、使用Jinja2模板引擎
    • 11.1 建立Flask项目
    • 11.2 创建并编辑HelloWorld/templates/default.html
    • 11.4 编辑HelloWorld/server.py
    • 11.5 运行与测试
    • 11.6 本节源码
  • 十二、自定义404等错误的响应
    • 12.1 示例1:简单入门
    • 12.2 示例2:自定义错误页面
    • 12.3 本节源码
  • 十三、用户会话
    • 13.1 建立Flask项目
    • 13.2 编辑HelloWorld/server.py
    • 13.3 代码的含义
    • 13.4 效果
    • 13.5 设置sessin的有效时间
    • 13.6 本节源码
  • 十四、使用Cookie
    • 14.1 建立Flask项目
    • 14.2 代码
    • 14.3 运行与测试
    • 14.4 本节源码
  • 十五、闪存系统 flashing system
    • 15.1 建立Flask项目
    • 15.2 编写HelloWorld/server.py
    • 15.3 效果
    • 15.4 高级用法
    • 15.5 在模板文件中获取flash的内容
    • 15.6 本节源码

一、简介

Flask是一个轻量级的基于Python的web框架。

本文适合有一定HTML、Python、网络基础的同学阅读。

这份文档中的代码使用 Python 3 运行。 
建议在 linux 下实践本教程中命令行操作、执行代码。

二、安装

通过pip3安装Flask即可:

$ sudo pip3 install Flask

进入python交互模式看下Flask的介绍和版本:

$ python3

>>> import flask
>>> print(flask.__doc__)

    flask
    ~~~~~

    A microframework based on Werkzeug.  It's extensively documented
    and follows best practice patterns.

    :copyright:  2010 by the Pallets team.
    :license: BSD, see LICENSE for more details.

>>> print(flask.__version__)
1.0.2

三、从 Hello World 开始

本节主要内容:使用Flask写一个显示”Hello World!”的web程序,如何配置、调试Flask。

3.1 Hello World

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

statictemplates目录是默认配置,其中static用来存放静态资源,例如图片、js、css文件等。templates存放模板文件。 
我们的网站逻辑基本在server.py文件中,当然,也可以给这个文件起其他的名字。

在server.py中加入以下内容:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run()

运行server.py:

$ python3 server.py
 * Running on http://127.0.0.1:5000/

打开浏览器访问http://127.0.0.1:5000/,浏览页面上将出现Hello World!。 
终端里会显示下面的信息:

127.0.0.1 - - [16/May/2014 10:29:08] "GET / HTTP/1.1" 200 -

变量app是一个Flask实例,通过下面的方式:

@app.route('/')
def hello_world():
    return 'Hello World!'

当客户端访问/时,将响应hello_world()函数返回的内容。注意,这不是返回Hello World!这么简单,Hello World!只是HTTP响应报文的实体部分,状态码等信息既可以由Flask自动处理,也可以通过编程来制定。

3.2 修改Flask的配置

app = Flask(__name__)

上面的代码中,python内置变量__name__的值是字符串__main__ 。Flask类将这个参数作为程序名称。当然这个是可以自定义的,比如app = Flask("my-app")

Flask默认使用static目录存放静态资源,templates目录存放模板,这是可以通过设置参数更改的:

app = Flask("my-app", static_folder="path1", template_folder="path2")

更多参数请参考__doc__

from flask import Flask
print(Flask.__doc__)

3.3 调试模式

上面的server.py中以app.run()方式运行,这种方式下,如果服务器端出现错误是不会在客户端显示的。但是在开发环境中,显示错误信息是很有必要的,要显示错误信息,应该以下面的方式运行Flask:

app.run(debug=True)

debug设置为True的另一个好处是,程序启动后,会自动检测源码是否发生变化,若有变化则自动重启程序。这可以帮我们省下很多时间。

3.4 绑定IP和端口

默认情况下,Flask绑定IP为127.0.0.1,端口为5000。我们也可以通过下面的方式自定义:

app.run(host='0.0.0.0', port=80, debug=True)

0.0.0.0代表电脑所有的IP。80是HTTP网站服务的默认端口。什么是默认?比如,我们访问网站http://www.example.com,其实是访问的http://www.example.com:80,只不过:80可以省略不写。

由于绑定了80端口,需要使用root权限运行server.py。也就是:

$ sudo python3 server.py

3.5 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-001

四、获取 URL 参数

URL参数是出现在url中的键值对,例如http://127.0.0.1:5000/?disp=3中的url参数是{'disp':3}

4.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

4.2 列出所有的url参数

在server.py中添加以下内容:

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    return request.args.__str__()

if __name__ == '__main__':
    app.run(port=5000, debug=True)

在浏览器中访问http://127.0.0.1:5000/?user=Flask&time&p=7&p=8,将显示:

ImmutableMultiDict([('user', 'Flask'), ('time', ''), ('p', '7'), ('p', '8')])

较新的浏览器也支持直接在url中输入中文(最新的火狐浏览器内部会帮忙将中文转换成符合URL规范的数据),在浏览器中访问http://127.0.0.1:5000/?info=这是爱,,将显示:

ImmutableMultiDict([('info', '这是爱,')])

浏览器传给我们的Flask服务的数据长什么样子呢?可以通过request.full_pathrequest.path来看一下:

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    print(request.path)
    print(request.full_path)
    return request.args.__str__()

if __name__ == '__main__':
    app.run(port=5000, debug=True)

浏览器访问http://127.0.0.1:5000/?info=这是爱,,运行server.py的终端会输出: 
1./

2./?info=%E8%BF%99%E6%98%AF%E7%88%B1%EF%BC%8C

4.3 获取某个指定的参数

例如,要获取键info对应的值,如下修改server.py:

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    return request.args.get('info')

if __name__ == '__main__':
    app.run(port=5000)

运行server.py,在浏览器中访问http://127.0.0.1:5000/?info=hello,浏览器将显示:

hello

不过,当我们访问http://127.0.0.1:5000/时候却出现了500错误

为什么为这样?

这是因为没有在URL参数中找到info。所以request.args.get('info')返回Python内置的None,而Flask不允许返回None。

解决方法很简单,我们先判断下它是不是None:

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    r = request.args.get('info')
    if r==None:
        # do something
        return ''
    return r

if __name__ == '__main__':
    app.run(port=5000, debug=True)

另外一个方法是,设置默认值,也就是取不到数据时用这个值:

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    r = request.args.get('info', 'hi')
    return r

if __name__ == '__main__':
    app.run(port=5000, debug=True)

函数request.args.get的第二个参数用来设置默认值。此时在浏览器访问http://127.0.0.1:5000/,将显示:

hi

4.4 如何处理多值

还记得上面有一次请求是这样的吗? http://127.0.0.1:5000/?user=Flask&time&p=7&p=8,仔细看下,p有两个值。

如果我们的代码是:

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    r = request.args.get('p')
    return r

if __name__ == '__main__':
    app.run(port=5000, debug=True)

在浏览器中请求时,我们只会看到7。如果我们需要把p的所有值都获取到,该怎么办?

不用get,用getlist

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    r = request.args.getlist('p')  # 返回一个list
    return str(r)

if __name__ == '__main__':
    app.run(port=5000, debug=True)

浏览器输入 http://127.0.0.1:5000/?user=Flask&time&p=7&p=8,我们会看到['7', '8']

4.5 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-002

五、获取POST方法传送的数据

作为一种HTTP请求方法,POST用于向指定的资源提交要被处理的数据。我们在某网站注册用户、写文章等时候,需要将数据传递到网站服务器中。并不适合将数据放到URL参数中,密码放到URL参数中容易被看到,文章数据又太多,浏览器不一定支持太长长度的URL。这时,一般使用POST方法。

本文使用python的requests库模拟浏览器。

安装方法:

$ sudo pip3 install requests

5.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

5.2 查看POST数据内容

以用户注册为例子,我们需要向服务器/register传送用户名name和密码password。如下编写HelloWorld/server.py。

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/register', methods=['POST'])
def register():
    print(request.headers)
    print(request.stream.read())
    return 'welcome'

if __name__ == '__main__':
    app.run(port=5000, debug=True)

`@app.route(‘/register’, methods=[‘POST’])是指url/register只接受POST方法。可以根据需要修改methods`参数,例如如果想要让它同时支持GET和POST,这样写:

@app.route('/register', methods=['GET', 'POST'])

浏览器模拟工具client.py内容如下:

import requests

user_info = {'name': 'letian', 'password': '123'}
r = requests.post("http://127.0.0.1:5000/register", data=user_info)

print(r.text)

运行HelloWorld/server.py,然后运行client.py。client.py将输出:

welcome

而HelloWorld/server.py在终端中输出以下调试信息(通过print输出):

Host: 127.0.0.1:5000
User-Agent: python-requests/2.19.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 24
Content-Type: application/x-www-form-urlencoded

b'name=letian&password=123'

前6行是client.py生成的HTTP请求头,由print(request.headers)输出。

请求体的数据,我们通过print(request.stream.read())输出,结果是:

b'name=letian&password=123'

5.3 解析POST数据

上面,我们看到post的数据内容是:

b'name=letian&password=123'

我们要想办法把我们要的name、password提取出来,怎么做呢?自己写?不用,Flask已经内置了解析器request.form

我们将服务代码改成:

from flask import Flask, request

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/register', methods=['POST'])
def register():
    print(request.headers)
    # print(request.stream.read()) # 不要用,否则下面的form取不到数据
    print(request.form)
    print(request.form['name'])
    print(request.form.get('name'))
    print(request.form.getlist('name'))
    print(request.form.get('nickname', default='little apple'))
    return 'welcome'

if __name__ == '__main__':
    app.run(port=5000, debug=True)

执行client.py请求数据,服务器代码会在终端输出:

Host: 127.0.0.1:5000
User-Agent: python-requests/2.19.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 24
Content-Type: application/x-www-form-urlencoded

ImmutableMultiDict([('name', 'letian'), ('password', '123')])
letian
letian
['letian']
little apple

request.form会自动解析数据。

request.form['name']request.form.get('name')都可以获取name对应的值。对于request.form.get()可以为参数default指定值以作为默认值。所以:

print(request.form.get('nickname', default='little apple'))

输出的是默认值

little apple

如果name有多个值,可以使用request.form.getlist('name'),该方法将返回一个列表。我们将client.py改一下:

import requests

user_info = {'name': ['letian', 'letian2'], 'password': '123'}
r = requests.post("http://127.0.0.1:5000/register", data=user_info)

print(r.text)

此时运行client.py,print(request.form.getlist('name'))将输出:

[u'letian', u'letian2']

5.4 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-003

六、处理和响应JSON数据

使用 HTTP POST 方法传到网站服务器的数据格式可以有很多种,比如「5. 获取POST方法传送的数据」讲到的name=letian&password=123这种用过&符号分割的key-value键值对格式。我们也可以用JSON格式、XML格式。相比XML的重量、规范繁琐,JSON显得非常小巧和易用。

6.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

6.2 处理JSON格式的请求数据

如果POST的数据是JSON格式,request.json会自动将json数据转换成Python类型(字典或者列表)。

编写server.py:

from flask import Flask, request

app = Flask("my-app")

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/add', methods=['POST'])
def add():
    print(request.headers)
    print(type(request.json))
    print(request.json)
    result = request.json['a'] + request.json['b']
    return str(result)

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=True)

编写client.py模拟浏览器请求:

import requests

json_data = {'a': 1, 'b': 2}

r = requests.post("http://127.0.0.1:5000/add", json=json_data)

print(r.text)

运行server.py,然后运行client.py,client.py 会在终端输出:

3

server.py 会在终端输出:

Host: 127.0.0.1:5000
User-Agent: python-requests/2.19.1
Accept-Encoding: gzip, deflate
Accept: */*
Connection: keep-alive
Content-Length: 16
Content-Type: application/json

{'a': 1, 'b': 2}

注意,请求头中Content-Type的值是application/json

6.3 响应JSON-方案1

响应JSON时,除了要把响应体改成JSON格式,响应头的Content-Type也要设置为application/json

编写server2.py:

from flask import Flask, request, Response
import json

app = Flask("my-app")

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/add', methods=['POST'])
def add():
    result = {'sum': request.json['a'] + request.json['b']}
    return Response(json.dumps(result),  mimetype='application/json')

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=True)

修改后运行。

编写client2.py:

import requests

json_data = {'a': 1, 'b': 2}

r = requests.post("http://127.0.0.1:5000/add", json=json_data)

print(r.headers)
print(r.text)

运行client.py,将显示:

{'Content-Type': 'application/json', 'Content-Length': '10', 'Server': 'Werkzeug/0.14.1 Python/3.6.4', 'Date': 'Sat, 07 Jul 2018 05:23:00 GMT'}

{"sum": 3}

上面第一段内容是服务器的响应头,第二段内容是响应体,也就是服务器返回的JSON格式数据。

另外,如果需要服务器的HTTP响应头具有更好的可定制性,比如自定义Server,可以如下修改add()函数:

@app.route('/add', methods=['POST'])
def add():
    result = {'sum': request.json['a'] + request.json['b']}
    resp = Response(json.dumps(result),  mimetype='application/json')
    resp.headers.add('Server', 'python flask')
    return resp

client2.py运行后会输出:

{'Content-Type': 'application/json', 'Content-Length': '10', 'Server': 'python flask', 'Date': 'Sat, 07 Jul 2018 05:26:40 GMT'}

{"sum": 3}

6.4 响应JSON-方案2

使用 jsonify 工具函数即可。

from flask import Flask, request, jsonify

app = Flask("my-app")

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/add', methods=['POST'])
def add():
    result = {'sum': request.json['a'] + request.json['b']}
    return jsonify(result)

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=True)

6.5 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-004

七、上传文件

上传文件,一般也是用POST方法。

7.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

7.2 上传文件

这一部分的代码参考自How to upload a file to the server in Flask

我们以上传图片为例: 
假设将上传的图片只允许’png’、’jpg’、’jpeg’、’gif’这四种格式,通过url/upload使用POST上传,上传的图片存放在服务器端的static/uploads目录下。

首先在项目HelloWorld中创建目录static/uploads

mkdir HelloWorld/static/uploads

werkzeug库可以判断文件名是否安全,例如防止文件名是../../../a.png,安装这个库:

$ sudo pip3 install werkzeug

server.py代码:

from flask import Flask, request

from werkzeug.utils import secure_filename
import os

app = Flask(__name__)

# 文件上传目录
app.config['UPLOAD_FOLDER'] = 'static/uploads/'
# 支持的文件格式
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'}  # 集合类型

# 判断文件名是否是我们支持的格式
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/upload', methods=['POST'])
def upload():
    upload_file = request.files['image']
    if upload_file and allowed_file(upload_file.filename):
        filename = secure_filename(upload_file.filename)
        # 将文件保存到 static/uploads 目录,文件名同上传时使用的文件名
        upload_file.save(os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename))
        return 'info is '+request.form.get('info', '')+'. success'
    else:
        return 'failed'

if __name__ == '__main__':
    app.run(port=5000, debug=True)

app.config中的config是字典的子类,可以用来设置自有的配置信息,也可以设置自己的配置信息。函数allowed_file(filename)用来判断filename是否有后缀以及后缀是否在app.config['ALLOWED_EXTENSIONS']中。

客户端上传的图片必须以image01标识。upload_file是上传文件对应的对象。app.root_path获取server.py所在目录在文件系统中的绝对路径。upload_file.save(path)用来将upload_file保存在服务器的文件系统中,参数最好是绝对路径,否则会报错(网上很多代码都是使用相对路径,但是笔者在使用相对路径时总是报错,说找不到路径)。函数os.path.join()用来将使用合适的路径分隔符将路径组合起来。

好了,定制客户端client.py:

import requests
file_data = {'image': open('Lenna.jpg', 'rb')}
user_info = {'info': 'Lenna'}
r = requests.post("http://127.0.0.1:5000/upload", data=user_info, files=file_data)
print(r.text)

运行client.py,当前目录下的Lenna.jpg将上传到服务器。

然后,我们可以在static/uploads中看到文件Lenna.jpg。

要控制上产文件的大小,可以设置请求实体的大小,例如:

app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 #16MB

不过,在处理上传文件时候,需要使用try:...except:...

如果要获取上传文件的内容可以:

file_content = request.files['image'].stream.read()

7.3 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-005

八、Restful URL

简单来说,Restful URL可以看做是对 URL 参数的替代。

8.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

8.2 编写代码

编辑server.py:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/user/')
def user(username):
    print(username)
    print(type(username))
    return 'hello ' + username

@app.route('/user//friends')
def user_friends(username):
    print(username)
    print(type(username))

    return 'hello ' + username

if __name__ == '__main__':
    app.run(port=5000, debug=True)

运行HelloWorld/server.py。使用浏览器访问http://127.0.0.1:5000/user/letian,HelloWorld/server.py将输出:

letian

而访问http://127.0.0.1:5000/user/letian/,响应为404 Not Found。

浏览器访问http://127.0.0.1:5000/user/letian/friends,可以看到:

Hello letian. They are your friends.

HelloWorld/server.py输出:

letian

8.3 转换类型

由上面的示例可以看出,使用 Restful URL 得到的变量默认为str对象。如果我们需要通过分页显示查询结果,那么需要在url中有数字来指定页数。按照上面方法,可以在获取str类型页数变量后,将其转换为int类型。不过,还有更方便的方法,就是用flask内置的转换机制,即在route中指定该如何转换。

新的服务器代码:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/page/')
def page(num):
    print(num)
    print(type(num))
    return 'hello world'

if __name__ == '__main__':
    app.run(port=5000, debug=True)

`@app.route(‘/page/int:num‘)`会将num变量自动转换成int类型。

运行上面的程序,在浏览器中访问http://127.0.0.1:5000/page/1,HelloWorld/server.py将输出如下内容:

1

如果访问的是http://127.0.0.1:5000/page/asd,我们会得到404响应。

在官方资料中,说是有3个默认的转换器:

int     accepts integers

float     like int but for floating point values

path     like the default but also accepts slashes

看起来够用了。

8.4 一个有趣的用法

如下编写服务器代码:

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/page/-')
def page(num1, num2):
    print(num1)
    print(num2)
    return 'hello world'

if __name__ == '__main__':
    app.run(port=5000, debug=True)

在浏览器中访问http://127.0.0.1:5000/page/11-22,HelloWorld/server.py会输出:

11

22

8.5 编写转换器

自定义的转换器是一个继承werkzeug.routing.BaseConverter的类,修改to_pythonto_url方法即可。to_python方法用于将url中的变量转换后供被`@app.route包装的函数使用,to_url方法用于flask.url_for`中的参数转换。

下面是一个示例,将HelloWorld/server.py修改如下:

from flask import Flask, url_for

from werkzeug.routing import BaseConverter

class MyIntConverter(BaseConverter):

    def __init__(self, url_map):
        super(MyIntConverter, self).__init__(url_map)

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return value * 2

app = Flask(__name__)
app.url_map.converters['my_int'] = MyIntConverter

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/page/')
def page(num):
    print(num)
    print(url_for('page', num=123))   # page 对应的是 page函数 ,num 对应对应`/page/`中的num,必须是str
    return 'hello world'

if __name__ == '__main__':
    app.run(port=5000, debug=True)

浏览器访问http://127.0.0.1:5000/page/123后,HelloWorld/server.py的输出信息是:

123

/page/123123

8.6 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-006

九、使用url_for生成链接

工具函数url_for可以让你以软编码的形式生成url,提供开发效率。

9.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

9.2 编写代码

编辑HelloWorld/server.py:

from flask import Flask, url_for

app = Flask(__name__)

@app.route('/')
def hello_world():
    pass

@app.route('/user/')
def user(name):
    pass

@app.route('/page/')
def page(num):
    pass

@app.route('/test')
def test():
    print(url_for('hello_world'))
    print(url_for('user', name='letian'))
    print(url_for('page', num=1, q='hadoop mapreduce 10%3'))
    print(url_for('static', filename='uploads/01.jpg'))
    return 'Hello'

if __name__ == '__main__':
    app.run(debug=True)

运行HelloWorld/server.py。然后在浏览器中访问http://127.0.0.1:5000/test,HelloWorld/server.py将输出以下信息:

/
/user/letian
/page/1?q=hadoop+mapreduce+10%253
/static/uploads/01.jpg

9.3 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-007

十、使用redirect重定向网址

redirect函数用于重定向,实现机制很简单,就是向客户端(浏览器)发送一个重定向的HTTP报文,浏览器会去访问报文中指定的url。

10.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

10.2 编写代码

使用redirect时,给它一个字符串类型的参数就行了。

编辑HelloWorld/server.py:

from flask import Flask, url_for, redirect

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/test1')
def test1():
    print('this is test1')
    return redirect(url_for('test2'))

@app.route('/test2')
def test2():
    print('this is test2')
    return 'this is test2'

if __name__ == '__main__':
    app.run(debug=True)

运行HelloWorld/server.py,在浏览器中访问http://127.0.0.1:5000/test1,浏览器的url会变成http://127.0.0.1:5000/test2,并显示:

this is test2

10.3 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-008

十一、使用Jinja2模板引擎

模板引擎负责MVC中的V(view,视图)这一部分。Flask默认使用Jinja2模板引擎。

Flask与模板相关的函数有:

  • flask.render_template(template_name_or_list, **context) 
    Renders a template from the template folder with the given context.
  • flask.render_template_string(source, **context) 
    Renders a template from the given template source string with the given context.
  • flask.get_template_attribute(template_name, attribute) 
    Loads a macro (or variable) a template exports. This can be used to invoke a macro from within Python code.

这其中常用的就是前两个函数。

这个实例中使用了模板继承、if判断、for循环。

11.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

11.2 创建并编辑HelloWorld/templates/default.html

内容如下:

<html>
<head>
    <title>
        {% if page_title %}
            {{ page_title }}
        {% endif %}
    </title>
</head>

<body>
    {% block body %}{% endblock %}

```
可以看到,在``标签中使用了if判断,如果给模板传递了`page_title`变量,显示之,否则,不显示。
``标签中定义了一个名为`body`的block,用来被其他模板文件继承。
### 11.3 创建并编辑HelloWorld/templates/user_info.html
内容如下:
```
{% extends "default.html" %}

{% block body %}
    {% for key in user_info %}

        {{ key }}: {{ user_info[key] }} 

    {% endfor %}
{% endblock %}

变量user_info应该是一个字典,for循环用来循环输出键值对。

11.4 编辑HelloWorld/server.py

内容如下:

from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/user')
def user():
    user_info = {
        'name': 'letian',
        'email': '123@aa.com',
        'age':0,
        'github': 'https://github.com/letiantian'
    }
    return render_template('user_info.html', page_title='letian\'s info', user_info=user_info)

if __name__ == '__main__':
    app.run(port=5000, debug=True)

render_template()函数的第一个参数指定模板文件,后面的参数是要传递的数据。

11.5 运行与测试

运行HelloWorld/server.py:

$ python3 HelloWorld/server.py

在浏览器中访问http://127.0.0.1:5000/user

查看网页源码:

<html>
<head>
    <title>
            letian&&9;s info
    </title>
</head>
<body>
        name: letian <br/>
        email: 123@aa.com <br/>
        age: 0 <br/>
        github: https://github.com/letiantian <br/>
</body>
</html>

11.6 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-009

十二、自定义404等错误的响应

要处理HTTP错误,可以使用flask.abort函数。

12.1 示例1:简单入门

建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

代码

编辑HelloWorld/server.py:

from flask import Flask, render_template_string, abort

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/user')
def user():
    abort(401)  # Unauthorized 未授权
    print('Unauthorized, 请先登录')

if __name__ == '__main__':
    app.run(port=5000, debug=True)

效果

运行HelloWorld/server.py,浏览器访问http://127.0.0.1:5000/user

要注意的是,HelloWorld/server.py中abort(401)后的print并没有执行。

12.2 示例2:自定义错误页面

代码

将服务器代码改为:

from flask import Flask, render_template_string, abort

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/user')
def user():
    abort(401)  # Unauthorized

@app.errorhandler(401)
def page_unauthorized(error):
    return render_template_string('
 Unauthorized
{{ error_info }}', error_info=error), 401

if __name__ == '__main__':
    app.run(port=5000, debug=True)

page_unauthorized函数返回的是一个元组,401 代表HTTP 响应状态码。如果省略401,则响应状态码会变成默认的 200。

效果

运行HelloWorld/server.py,浏览器访问http://127.0.0.1:5000/user

12.3 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-010

十三、用户会话

session用来记录用户的登录状态,一般基于cookie实现。

下面是一个简单的示例。

13.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

13.2 编辑HelloWorld/server.py

内容如下:

from flask import Flask, render_template_string, \
    session, request, redirect, url_for

app = Flask(__name__)

app.secret_key = 'F12Zr47j\3yX R~X@H!jLwf/T'

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/login')
def login():
     return render_template_string(page)
@app.route('/do_login', methods=['POST'])
def do_login():
    name = request.form.get('user_name')
    session['user_name'] = name
    return 'success'

@app.route('/show')
def show():
    return session['user_name']

@app.route('/logout')
def logout():
    session.pop('user_name', None)
    return redirect(url_for('login'))

if __name__ == '__main__':
    app.run(port=5000, debug=True)

13.3 代码的含义

app.secret_key用于给session加密。

/login中将向用户展示一个表单,要求输入一个名字,submit后将数据以post的方式传递给/do_login/do_login将名字存放在session中。

如果用户成功登录,访问/show时会显示用户的名字。此时,打开firebug等调试工具,选择session面板,会看到有一个cookie的名称为session

/logout用于登出,通过将session中的user_name字段pop即可。Flask中的session基于字典类型实现,调用pop方法时会返回pop的键对应的值;如果要pop的键并不存在,那么返回值是pop()的第二个参数。

另外,使用redirect()重定向时,一定要在前面加上return

13.4 效果

进入http://127.0.0.1:5000/login,输入name,点击submit

进入http://127.0.0.1:5000/show查看session中存储的name:

13.5 设置sessin的有效时间

下面这段代码来自Is there an easy way to make sessions timeout in flask?

from datetime import timedelta
from flask import session, app

session.permanent = True
app.permanent_session_lifetime = timedelta(minutes=5)

这段代码将session的有效时间设置为5分钟。

13.6 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-011

十四、使用Cookie

Cookie是存储在客户端的记录访问者状态的数据。具体原理,请见 http://zh.wikipedia.org/wiki/Cookie 。 常用的用于记录用户登录状态的session大多是基于cookie实现的。

cookie可以借助flask.Response来实现。下面是一个示例。

14.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

14.2 代码

修改HelloWorld/server.py:

from flask import Flask, request, Response, make_response
import time

app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'hello world'

@app.route('/add')
def login():
    res = Response('add cookies')
    res.set_cookie(key='name', value='letian', expires=time.time()+6*60)
    return res

@app.route('/show')
def show():
    return request.cookies.__str__()

@app.route('/del')
def del_cookie():
    res = Response('delete cookies')
    res.set_cookie('name', '', expires=0)
    return res

if __name__ == '__main__':
    app.run(port=5000, debug=True)

由上可以看到,可以使用Response.set_cookie添加和删除cookie。expires参数用来设置cookie有效时间,它的值可以是datetime对象或者unix时间戳,笔者使用的是unix时间戳。

res.set_cookie(key='name', value='letian', expires=time.time()+6*60)

上面的expire参数的值表示cookie在从现在开始的6分钟内都是有效的。

要删除cookie,将expire参数的值设为0即可:

res.set_cookie('name', '', expires=0)

set_cookie()函数的原型如下:

set_cookie(key, value=’’, max_age=None, expires=None, path=’/‘, domain=None, secure=None, httponly=False)

Sets a cookie. The parameters are the same as in the cookie Morsel object in the Python standard library but it accepts unicode data, too. 
Parameters:

key – the key (name) of the cookie to be set. 
value – the value of the cookie. 
max_age – should be a number of seconds, or None (default) if the cookie should last only as long as the client’s browser session.

expires – should be a datetime object or UNIX timestamp.

domain – if you want to set a cross-domain cookie. For example, domain=”.example.com” will set a cookie that is readable by the domain www.example.com, foo.example.com etc. Otherwise, a cookie will only be readable by the domain that set it.

path – limits the cookie to a given path, per default it will span the whole domain.

14.3 运行与测试

运行HelloWorld/server.py:

$ python3 HelloWorld/server.py

使用浏览器打开http://127.0.0.1:5000/add,浏览器界面会显示

add cookies

下面查看一下cookie,如果使用firefox浏览器,可以用firebug插件查看。打开firebug,选择Cookies选项,刷新页面,可以看到名为name的cookie,其值为letian

在“网络”选项中,可以查看响应头中类似下面内容的设置cookie的HTTP「指令」:

Set-Cookie: name=letian; Expires=Sun, 29-Jun-2014 05:16:27 GMT; Path=/

在cookie有效期间,使用浏览器访问http://127.0.0.1:5000/show,可以看到:

{'name': 'letian'}

14.4 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-012

十五、闪存系统 flashing system

Flask的闪存系统(flashing system)用于向用户提供反馈信息,这些反馈信息一般是对用户上一次操作的反馈。反馈信息是存储在服务器端的,当服务器向客户端返回反馈信息后,这些反馈信息会被服务器端删除。

下面是一个示例。

15.1 建立Flask项目

按照以下命令建立Flask项目HelloWorld:

mkdir HelloWorld
mkdir HelloWorld/static
mkdir HelloWorld/templates
touch HelloWorld/server.py

15.2 编写HelloWorld/server.py

内容如下:

from flask import Flask, flash, get_flashed_messages
import time

app = Flask(__name__)
app.secret_key = 'some_secret'

@app.route('/')
def index():
    return 'hi'

@app.route('/gen')
def gen():
    info = 'access at '+ time.time().__str__()
    flash(info)
    return info

@app.route('/show1')
def show1():
    return get_flashed_messages().__str__()

@app.route('/show2')
def show2():
    return get_flashed_messages().__str__()

if __name__ == "__main__":
    app.run(port=5000, debug=True)

15.3 效果

运行服务器:

$ python3 HelloWorld/server.py

打开浏览器,访问http://127.0.0.1:5000/gen,浏览器界面显示(注意,时间戳是动态生成的,每次都会不一样,除非并行访问):

access at 1404020982.83

查看浏览器的cookie,可以看到session,其对应的内容是:

.eJyrVopPy0kszkgtVrKKrlZSKIFQSUpWSknhYVXJRm55UYG2tkq1OlDRyHC_rKgIvypPdzcDTxdXA1-XwHLfLEdTfxfPUn8XX6DKWCAEAJKBGq8.BpE6dg.F1VURZa7VqU9bvbC4XIBO9-3Y4Y

再一次访问http://127.0.0.1:5000/gen,浏览器界面显示:

access at 1404021130.32

cookie中session发生了变化,新的内容是:

.eJyrVopPy0kszkgtVrKKrlZSKIFQSUpWSknhYVXJRm55UYG2tkq1OlDRyHC_rKgIvypPdzcDTxdXA1-XwHLfLEdTfxfPUn8XX6DKWLBaMg1yrfCtciz1rfIEGxRbCwAhGjC5.BpE7Cg.Cb_B_k2otqczhknGnpNjQ5u4dqw

然后使用浏览器访问http://127.0.0.1:5000/show1,浏览器界面显示:

['access at 1404020982.83', 'access at 1404021130.32']

这个列表中的内容也就是上面的两次访问http://127.0.0.1:5000/gen得到的内容。此时,cookie中已经没有session了。

如果使用浏览器访问http://127.0.0.1:5000/show1或者http://127.0.0.1:5000/show2,只会得到:

[]

15.4 高级用法

flash系统也支持对flash的内容进行分类。修改HelloWorld/server.py内容:

from flask import Flask, flash, get_flashed_messages
import time

app = Flask(__name__)
app.secret_key = 'some_secret'

@app.route('/')
def index():
    return 'hi'

@app.route('/gen')
def gen():
    info = 'access at '+ time.time().__str__()
    flash('show1 '+info, category='show1')
    flash('show2 '+info, category='show2')
    return info

@app.route('/show1')
def show1():
    return get_flashed_messages(category_filter='show1').__str__()

@app.route('/show2')
def show2():
    return get_flashed_messages(category_filter='show2').__str__()

if __name__ == "__main__":
    app.run(port=5000, debug=True)

某一时刻,浏览器访问http://127.0.0.1:5000/gen,浏览器界面显示:

access at 1404022326.39

不过,由上面的代码可以知道,此时生成了两个flash信息,但分类(category)不同。

使用浏览器访问http://127.0.0.1:5000/show1,得到如下内容:

['1 access at 1404022326.39']

而继续访问http://127.0.0.1:5000/show2,得到的内容为空:

[]

15.5 在模板文件中获取flash的内容

在Flask中,get_flashed_messages()默认已经集成到Jinja2模板引擎中,易用性很强。

15.6 本节源码

https://github.com/letiantian/Learn-Flask/tree/master/flask-demo-01 3

到此这篇关于Python使用Web框架Flask开发项目的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Python Web框架Flask中使用七牛云存储实例

    对于小型站点,使用七牛云存储的免费配额已足够为站点提供稳定.快速的存储服务 七牛云存储已有Python SDK,对它进行简单封装后,就可以直接在Flask中使用了,项目代码见GitHub上Flask-QiniuStorage. 使用示例代码: 复制代码 代码如下: from flask import Flask from flask_qiniustorage import Qiniu   QINIU_ACCESS_KEY = '七牛 Access Key' QINIU_SECRET_KEY =

  • 在Python的Flask框架中构建Web表单的教程

    尽管Flask的request对象提供的支持足以处理web表单,但依然有许多任务会变得单调且重复.表单的HTML代码生成和验证提交的表单数据就是两个很好的例子. Flask-WTF扩展使得处理web表单能获得更愉快的体验.该扩展是一个封装了与框架无关的WTForms包的Flask集成. Flask-WTF和它的依赖集可以通过pip来安装: (venv) $ pip install flask-wtf 1.跨站请求伪造(CSRF)保护 默认情况下,Flask-WTF保护各种形式对跨站请求伪造(CS

  • Python Web框架Flask中使用新浪SAE云存储实例

    对于部署在新浪应用引擎SAE上的项目,使用新浪SAE云存储是不错的存储方案. 新浪SAE云存储仅能在SAE环境中正常使用,对它进行简单封装后,可以直接在Flask中使用,项目代码见GitHub上Flask-SaeStorage. 使用示例代码: 复制代码 代码如下: from flask import Flask from flask_saestorage import SaeStorage   SAE_ACCESS_KEY = 'SAE Access Key' SAE_SECRET_KEY =

  • 在python的WEB框架Flask中使用多个配置文件的解决方法

    有些框架本身就支持多配置文件,例如Ruby On Rails,nodejs下的expressjs.python下的Flask虽然本身支持配置文件管理, 但单纯使用from_object和from_envvar却不是那么方便.有没有更好的办法? 答案是Flask-Environments这个包.它能通过FLASK_ENV环境变量自动选择开发环境配置或生产环境配置.使用之前要先安装: 复制代码 代码如下: $ sudo pip install Flask-Environments 然后修改confi

  • Python flask框架如何显示图像到web页面

    代码如下 webfig1.py from flask import Flask from flask import render_template import matplotlib.pyplot as plt import io import base64 app = Flask(__name__) @app.route('/') def build_plot(): img = io.BytesIO() y = [1,2,3,4,5] x = [0,2,1,3,4] plt.plot(x,y)

  • Python的Flask框架中web表单的教程

     概要 在前面章节我们为主页定义了一个简单的模板,部分尚未实现的模块如用户或帖子等使用模拟的对象作为临时占位. 本章我们将看到如何利用web表单填补这些空白. web表单是web应用中最基本的构建要素,我们将通过表单来实现用户发帖和应用登录功能. 完成本章内容你需要基于前面章节完成的微博应用代码,请确认这些代码已安装并能正常运行. 配置 Flask-WTF是WTForms项目的Flask框架扩展,我们将用他来帮助我们处理web表单. 大部分Flask扩展都需要定义相关配置项,所以我们先来在应用根

  • Python Web框架Flask信号机制(signals)介绍

    信号(signals) Flask信号(signals, or event hooking)允许特定的发送端通知订阅者发生了什么(既然知道发生了什么,那我们可以知道接下来该做什么了). Flask提供了一些信号(核心信号)且其它的扩展提供更多的信号.信号是用于通知订阅者,而不应该鼓励订阅者修改数据.相关信号请查阅文档. 信号依赖于Blinker库. 钩子(hooks) Flask钩子(通常出现在蓝图或应用程序现存的方法中,比如一些内置装饰器,例如before_request)不需要Blinker

  • Python Web框架Flask中使用百度云存储BCS实例

    对于部署在百度应用引擎BAE上的项目,使用百度云存储BCS(Baidu Cloud Storage)是不错的存储方案. 百度云存储已有Python SDK,对它进行简单封装后,就可以直接在Flask中使用了,项目代码见GitHub上Flask-BCS. 使用示例代码: 复制代码 代码如下: from flask import Flask from flask_bcs import BCS   BCS_HOST = 'BCS HOST' BCS_ACCESS_KEY = 'BCS Access K

  • Python Web框架Flask下网站开发入门实例

    一.Flask简介 Flask 是一个 Python 实现的 Web 开发微框架.官网:http://flask.pocoo.org/ 二.Demo 1.代码结构 复制代码 代码如下: . ├── blog.py ├── static │   ├── css │   │   └── index.css │   ├── images │   │   ├── cat.jpg │   │   └── sheying1229.jpg │   └── js └── templates     ├── in

  • Python使用Web框架Flask开发项目

    目录 一.简介 二.安装 三.从 Hello World 开始 3.1 Hello World 3.2 修改Flask的配置 3.3 调试模式 3.4 绑定IP和端口 3.5 本节源码 四.获取 URL 参数 4.1 建立Flask项目 4.2 列出所有的url参数 4.3 获取某个指定的参数 4.4 如何处理多值 4.5 本节源码 五.获取POST方法传送的数据 5.1 建立Flask项目 5.2 查看POST数据内容 5.3 解析POST数据 5.4 本节源码 六.处理和响应JSON数据 6

  • Python常用Web框架Django、Flask与Tornado介绍

    web框架是什么? web开发框架是一组工具,同时也提供了非常多的资源,供软件开发人员构建和管理网站.提供web服务.编写web应用程序.它是一个抽象工具,能使开发应用程序和重复使用代码的过程变得更容易. 为什么需要web开发框架? 进行自定义软件开发时,web开发框架让整个过程变得更容易,因而开发速度更快.更高效.许多开发框架都很便宜,这也使得整个客户机的成本更小. 一个被广泛使用的框架安全性更高.这主要依赖于该框架背后的社区,在这里,用户成为长期的测试人员,并可以提供修复. 如果发现了安全漏

  • Python之Web框架Django项目搭建全过程

    Python之Web框架Django项目搭建全过程 IDE说明: Win7系统 Python:3.5 Django:1.10 Pymysql:0.7.10 Mysql:5.5 注:可通过pip freeze查看已安装库版本信息. Django 是由 Python 开发的一个免费的开源网站框架,可以用于快速搭建高性能,优雅的网站! Django 特点 强大的数据库功能 用python的类继承,几行代码就可以拥有一个丰富,动态的数据库操作接口(API),如果需要你也能执行SQL语句. 自带的强大的后

  • python web框架Flask实现图形验证码及验证码的动态刷新实例

    下列代码都是以自己的项目实例讲述的,相关的文本内容很少,主要说明全在代码注释中 自制图形验证码 这里所说的图形验证码都是自制的图形,通过画布.画笔.画笔字体的颜色绘制而成的.将验证码封装成一个类比较好管理,代码里有绝对详细的注释,当然大家可以直接复制. 里面涉及的字体都是从系统电脑上自带的,大家直接复制当前目录下就可以了. 主目录/utils/captcha/__init__.py import random import string # Image:一个画布 # ImageDraw:一个画笔

  • python异步Web框架sanic的实现

    我们继续学习Python异步编程,这里将介绍异步Web框架sanic,为什么不是tornado?从框架的易用性来说,Flask要远远比tornado简单,可惜flask不支持异步,而sanic就是类似Flask语法的异步框架. github:https://github.com/huge-success/sanic 不过sanic对环境有要求: macOS/linux python 3.6+ 不过,我在macOS上安装 sanic 还是踩了坑.依赖库ujson一直安装失败.最后不得不卸载官方py

  • 轻量级的Web框架Flask 中模块化应用的实现

    Flask是一个轻量级的Web框架.虽然是轻量级的,但是对于组件一个大型的.模块化应用也是能够实现的,"蓝图"就是这样一种实现.对于模块化应用的实现,在Flask 0.2版本中进行了设计.本文暂时不对"蓝图"做详细的介绍,而是先从0.2版本中的Module类的实现讲起.其实,"蓝图"的实现和Module类的实现很相似. 为什么实现模块化应用 对于大型应用而言,随着功能的不断增加,整个应用的规模也会扩大.按照一定的规则将应用的不同部分进行模块化,不

  • 在Python的web框架中配置app的教程

    有了Web框架和ORM框架,我们就可以开始装配App了. 通常,一个Web App在运行时都需要读取配置文件,比如数据库的用户名.口令等,在不同的环境中运行时,Web App可以通过读取不同的配置文件来获得正确的配置. 由于Python本身语法简单,完全可以直接用Python源代码来实现配置,而不需要再解析一个单独的.properties或者.yaml等配置文件. 默认的配置文件应该完全符合本地开发环境,这样,无需任何设置,就可以立刻启动服务器. 我们把默认的配置文件命名为config_defa

  • Python的Web框架Django介绍与安装方法

    简介 Python下有许多款不同的 Web 框架.Django是重量级选手中最有代表性的一位.许多成功的网站和APP都基于Django. Django 是一个开放源代码的 Web 应用框架,由 Python 写成. Django 遵守 BSD 版权,初次发布于 2005 年 7 月, 并于 2008 年 9 月发布了第一个正式版本 1.0 . Django 采用了 MVT 的软件设计模式,即模型(Model),视图(View)和模板(Template). Django 版本对应的 Python

随机推荐