java有一套spring但是略显笨重而且对于个人平时玩玩来说总感觉没必要(如果掌握了的话效率还是不错的) python的web框架有django和flask等
先安装环境
pip install flask
即可 安装最新版
按照官网教程
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'Hello, World!'
WSGI的介绍:
全称Python Web Server Gateway Interface,指定了web服务器和Python web应用或web框架之间的标准接口,以提高web应用在一系列web服务器间的移植性。 具体可查看
从以上介绍我们可以看出:
请不要使用 flask.py
作为应用名称,这会与 Flask 本身发生冲突。
flask 命令或者 python 的 -m
开关来运行这个应用。在 运行应用之前,需要在终端里导出 FLASK_APP
环境变量:
$ export FLASK_APP=hello.py
$ flask run
* Running on http://127.0.0.1:5000/
通过flask run -h [host] -p [port]指定主机和端口
export FLASK_ENV=development
打开开发环境的功能
还可以通过导出 FLASK_DEBUG=1
来单独控制调试模式的开关,绝对不能在生产环境 中使用调试器
现代 web 应用都使用有意义的 URL ,这样有助于用户记忆,网页会更得到用户的青睐, 提高回头率
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello_world():
return 'index page'
# print(__name__)
@app.route('/hello')
def hello():
return 'hello world'
可以动态变化 URL 的某些部分, 还可以为一个函数指定多个规则
@app.route('/user/<username>')
def show_user_profile(username):
# 显示用户名
return 'User {}'.format(username)
@app.route('/post/<int:post_id>')
def show_post(post_id):
# 显示提交整型的用户"id"的结果,注意"int"是将输入的字符串形式转换为整型数据
return 'Post {}'.format(post_id)
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# 显示 /path/ 之后的路径名
return 'Subpath {}'.format(subpath)
转换器的主要类型如下:
类型 | 含义 |
---|---|
string | 默认的数据类型,接受没有任何斜杠“/”的字符串 |
int | 接受整型 |
float | 接受浮点类型 |
path | 和 string 类似,但是接受斜杠“/” |
uuid | 只接受 uuid 字符串 |
以下两条规则的不同之处在于是否使用尾部的斜杠。:
@app.route('/projects/')
def projects():
return 'The project page'
@app.route('/about')
def about():
return 'The about page'
projects
的 URL 是中规中矩的,尾部有一个斜杠,看起来就如同一个文件夹。 访问一个没有斜杠结尾的 URL 时 Flask 会自动进行重定向,帮你在尾部加上一个斜杠。
about
的 URL 没有尾部斜杠,因此其行为表现与一个文件类似。如果访问这个 URL 时添加了尾部斜杠就会得到一个 404 错误。这样可以保持 URL 唯一,并帮助 搜索引擎避免重复索引同一页面。
使用url_for()函数
函数用于构建指定函数的 URL。它把函数名称作为第一个 参数。它可以接受任意个关键字参数,每个关键字参数对应 URL 中的变量。未知变量 将添加到 URL 中作为查询参数。
为什么不在把 URL 写死在模板中,而要使用反转函数 动态构建?
/myapplication
中,不在 /
中), 会为你妥善处理。Web 应用使用不同的 HTTP 方法处理 URL 。当你使用 Flask 时,应当熟悉 HTTP 方法。 缺省情况下,一个路由只回应 GET
请求。 可以使用 装饰器的 methods
参数来处理不同的 HTTP 方法:
from flask import request
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
return do_the_login()
else:
return show_the_login_form()
如果当前使用了 GET 方法, Flask 会自动添加 HEAD
方法支持,并且同时还会 按照 来处理 HEAD
请求。同样, OPTIONS
也会自动实现。
动态的 web 应用也需要静态文件,一般是 CSS 和 JavaScript 文件。理想情况下你的 服务器已经配置好了为你的提供静态文件的服务。但是在开发过程中, Flask 也能做好 这项工作。只要在你的包或模块旁边创建一个名为 static
的文件夹就行了。 静态文件位于应用的 /static
中。
使用特定的 'static'
端点就可以生成相应的 URL
url_for('static', filename='style.css')
这个静态文件在文件系统中的位置应该是 static/style.css
。
在 Python 内部生成 HTML 不好玩,且相当笨拙。因为你必须自己负责 HTML 转义, 以确保应用的安全。因此, Flask 自动为你配置 模板引擎
Flask 将会在 templates
文件夹中寻找模板。因此如果你的应用是个模块,这个文件夹在模块的旁边,如果它是一个包,那么这个文件夹在你的包里面
<!DOCTYPE html>
<title>Hello From Flask</title>
{% if name %}
<!-- 如果 name 不为空则将 name 渲染出来 -->
<h1>Hello {{ name }}!</h1>
{% else %}
<!-- 如果 name 为空则打印 Hello World! -->
<h1>Hello World!</h1>
{% endif %}
在模板中你也可以使用 、 和 对象,也能使用函数 。
模板继承是十分有用的。如果想要知道模板继承如何工作的话,请阅读文档。基本的模板继承使得某些特定元素(如标题、导航和页脚)在每一页成为可能
引入css文件
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<link
rel="stylesheet"
type="text/css"
href="{{ url_for('static', filename='style.css') }}"
/>
</head>
<body>
<h1>Hello ShiYanLou {{name}}</h1>
</body>
</html>
在 Flask 中由全局对象 request
来提供这些信息。如果你有一定的 Python 经验,你会好奇这个对象怎么可能是全局的,并且 Flask 是怎么还能保证线程安全。答案是上下文作用域
首先你需要从 flask 模块中导入 request
:
from flask import request
当前请求的方法可以用method
属性来访问。你可以用form
属性来访问表单数据 (数据在 POST
或者PUT
中传输)。
如果在form
属性中不存在上述键值会发生些什么?在这种情况下会触发一个特别的 KeyError
。你可以像捕获标准的KeyError
一样来捕获它,如果你不这样去做,会显示一个HTTP 400 Bad Request
错误页面。所以很多情况下你不需要处理这个问题。
你可以用args
属性来接收在URL ( ?key=value )
中提交的参数:
searchword = request.args.get('key', '')
我们推荐使用get
来访问 URL 参数或捕获KeyError
,因为用户可能会修改 URL,向他们显示一个400 bad request
页面不是用户友好的。
你能够很容易地用 Flask 处理文件上传。只要确保在你的 HTML 表单中不要忘记设置属性 enctype="multipart/form-data"
,否则浏览器将不会传送文件。
上传的文件是存储在内存或者文件系统上一个临时位置。你可以通过请求对象中files
属性访问这些文件。每个上传的文件都会存储在这个属性字典里。它表现得像一个标准的 Python file
对象,但是它同样具有save()
方法,该方法允许你存储文件在服务器的文件系统上。
已上传的文件被储存在内存或文件系统的临时位置。你可以通过请求对象 files
属性来访问上传的文件。每个上传的文件都储存在这个 字典型属性中。这个属性基本和标准 Python file
对象一样,另外多出一个 用于把上传文件保存到服务器的文件系统中的 方法。下例展示其如何运作:
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
如果你想要知道在上传到你的应用之前在客户端的文件名称,你可以访问filename
属性。但请记住永远不要信任这个值,因为这个值可以伪造。如果你想要使用客户端的文件名来在服务器上存储文件,把它传递到 Werkzeug
提供给你的 secure_filename()
函数:
from flask import request
from werkzeug import secure_filename
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/' + secure_filename(f.filename))
...
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
下一个函数检查扩展名是否合法,上传文件,把用户重定向到已上传文件的 URL:
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
'''
那么 函数到底是有什么用?有一条原 则是“永远不要信任用户输入”。这条原则同样适用于已上传文件的文件名。所有提 交的表单数据可能是伪造的,文件名也可以是危险的。此时要谨记:在把文件保存到 文件系统之前总是要使用这个函数对文件名进行安检。
要访问 cookies ,可以使用 属性。可以使用响应 对象 的 方法来设置 cookies 。请求对象的 属性是一个包含了客户端传输的所有 cookies 的字典。在 Flask 中,如果使用 ,那么就不要直接使用 cookies ,因为 比较安全一些。
读取 cookies:
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')
# use cookies.get(key) instead of cookies[key] to not get a
# KeyError if the cookie is missing.
使用 函数可以重定向。使用 可以 更早退出请求,并返回错误代码:
from flask import abort, redirect, url_for
@app.route('/')
def index():
return redirect(url_for('login'))
@app.route('/login')
def login():
abort(401)
this_is_never_executed()
上例实际上是没有意义的,它让一个用户从索引页重定向到一个无法访问的页面(401 表示禁止访问)。但是上例可以说明重定向和出错跳出是如何工作的。
缺省情况下每种出错代码都会对应显示一个黑白的出错页面。使用 装饰器可以定制出错页面:
from flask import render_template
@app.errorhandler(404)
def page_not_found(error):
return render_template('page_not_found.html'), 404
注意 后面的 404
,这表示页面对就的出错 代码是 404 ,即页面不存在。缺省情况下 200 表示:一切正常
一个视图函数的返回值会被自动转换为一个响应对象。如果返回值是一个字符串,它被转换成一个响应主体是该字符串,错误代码为 200 OK
,媒体类型为text/html
的响应对象。Flask 把返回值转换成响应对象的逻辑如下:
response, status, headers
) 形式且至少含有其中的一个元素。status
值将会覆盖状态代码,headers
可以是一个列表或额外的消息头值字典。除了请求对象之外还有一种称为 的对象,允许你在不同请求 之间储存信息。这个对象相当于用密钥签名加密的 cookie ,即用户可以查看你的 cookie ,但是如果没有密钥就无法修改它。
使用会话之前你必须设置一个密钥。举例说明:
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
# Set the secret key to some random bytes. Keep this really secret!
app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'
@app.route('/')
def index():
if 'username' in session:
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
这里用到的 是用来转义的。如果不使用模板引擎就可以像上例 一样使用这个函数来转义
好的应用和用户界面全部是关于反馈。如果用户得不到足够的反馈,他们可能会变得讨厌这个应用。Flask 提供了一个真正的简单的方式来通过消息闪现系统给用户反馈。消息闪现系统基本上使得在请求结束时记录信息并在下一个 (且仅在下一个)请求中访问。通常结合模板布局来显示消息。
使用flash()
方法来闪现一个消息,使用get_flashed_messages()
能够获取消息,get_flashed_messages()
也能用于模板中。
有时候你会遇到一种情况:理论上来说你处理的数据应该是正确的,然而实际上并不正确。比如你可能有一些客户端代码,代码向服务器发送一个 HTTP 请求,但是显然它是错误的。这可能是由于用户篡改数据,或客户端代码失败。大部分时候针对这一情况返回400 Bad Request
就可以了,但是有时候不能这样做,代码必须继续工作。
你也有可能想要记录一些发生的不正常事情。这时候日志就派上用处。从 Flask 0.3 开始日志记录是预先配置好的
如果你想给你的应用添加 WSGI 中间件,你可以封装内部 WSGI 应用。例如如果你想使用 Werkzeug 包中的某个中间件来应付 lighttpd 中的 bugs,你可以这样做:
from werkzeug.contrib.fixers import LighttpdCGIRootFix
app.wsgi_app = LighttpdCGIRootFix(app.wsgi_app)
包括四个视图函数的编写:主页视图、新建博客视图、登录视图和等初始图以及三个模板文件。最后编写了针对页面进行美化的 style.css 文件。完成后,即可启动项目并执行登录、编写博客等操作