一个简单的Flask项目
# encoding:utf-8
from flask import Flask
'''app是一个实例,一个项目只能拥有一个实例'''
app = Flask(__name__)
'''设置为调试模式'''
app.debug = True
@app.route("/")
def hello():
'''最简单的一个实例'''
return "Hello World"
if __name__=="__main__":
app.run()
程序解析
首先,我们导入了Flask类。这个类的实例将会是我们的WSGI 应用程序
接下来,我们创建一个该类的实例,第一个参数是应用模块或者包的名称。也就是main
我们使用route()装饰器告诉Flask 什么样的URL 能触发我们的函数
这个函数的名字也在生成URL 时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息。
最后我们用run()函数来让应用运行在本地服务器上。 其中if name=='main':确保服务器只会在该脚本被Python 解释器直接执行的时候才会运行,而不是作为模块导入的时候。
app.debug = True是将项目设置为调试模式
关闭服务器按 Ctrl + C
调试模式
第一种方式
app = Flask(__name__)
app.debug = True
第二种方式
app = Flask(__name__)
if __name__=="__main__":
app.run(debug=True)
路由装饰器
- 本质上就是域名后面加的一个相对路径
路由装饰器
@app.route('/')
def index():
return 'Index'
--------访问方式--------
127.0.0.1:5000
@app.route('/hello/')
def hello():
return '<h1>Hello world!</h1>'
--------访问方式--------
127.0.0.1:5000/hello/
路由装饰器变量
@app.route('/user/<name>')
def showUserName(name):
return "User %s" %name
@app.route('/post/<int:post_id>')
def showPostId(post_id):
return "Post %d" %post_id
@app.route('/post/<float:post_id>')
def showPostId(post_id):
return "Post %f" %post_id
路由的注意点
装饰器url的末尾必须加上/,不加容易产生404 Not Found
变量名必须和下面函数的参数名保持一致
如果是int或float类型,不能直接return,必须要转换为字符串格式才可以
重定向和错误
from flask import redirect
@app.route("/redir/")
def redir():
return redirect("/index/")
@app.route("/redir/<name>")
def redirName(name)
return redirect(url_for("showUserName",name=name))
重定向
注意导包 from flask import redirect
redirect函数的作用是只要你调用了当前函数装饰器的url,就会重定向到redirect函数中的url中
url_for函数,第一个参数重定向到的方法名,后面可以接参数,第一个name为重定向到的函数的参数名,第二个参数为当前函数参数名
反向构建通常比硬编码的描述性更好。允许一次性修改URL,而不用到处边找边改。
URL 构建会转义特殊字符和Unicode 数据,免去你很多麻烦
错误
from flask import abort
@app.route("/abort/")
def abort1():
abort(404)
错误详解
首先导包 from flask import abort
然后abort不需要return
返回码记得不要写错
使用Flask-Script支持命令行选项
from flask_script import Manager
manager = Manager(app)
if __name__ == '__main__':
manager.run()
解析
导包Manager
使用Manager代理app
manager.run()代替app.run():替代了run里面的方法,可以直接在运行的时候加上命令参数替代run函数的参数
python hello.py runserver -d -r --host 0.0.0.0 --port 5000
命令行的参数
参数 | 描述 |
---|---|
--host HOST | 设置host为 HOST |
--port PORT | 设置port为PORT |
-d | 设置以debug模式运行而非run模式 |
-r | 设置自动重新载入(app.debug为True) |
请求与相应
HTTP方法
GET方法:获取服务器资源
POST方法:提交数据到服务器
获取请求的headers
from flask import request
@app.route('/useragent/')
def userAgent():
user_agent=request.headers.get('User-Agent')
return "<p>Your browser %s</p>"%user_agent
响应
@app.route('/')
def index():
return '<h1>Bad Request</h1>', 400
from flask import make_response
@app.route('/response/')
def response():
resp = make_response('<h1>Bad Request</h1>',400)
return resp
响应解析
第一个为返回的信息,第二个为状态码
视图函数直接返回一个元组(response,status,headers)
视图函数返回一个make_resonse()函数产生的响应对象
Cookies
通过请求对象的cookies属性来访问 Cookies
通过响应对象的set_cookie方法来设置 Cookies
Cookies代码
@app.route('/cookie/')
def cookie():
resp = make_response('set cookie')
resp.set_cookie('name','myname')
print(request.cookies.get('name'))
return resp
后面写的相同的键会覆盖前面的,但是不同的键会保留前面的
请求钩子
before_first_request:在处理第一个请求之前运行
before_request:在每次请求之前运行
after_request:如果没有未处理的异常抛出,在每次请求之后运行
teardown_request:即使有未处理的异常抛出,也在每次请求之后运行
请求钩子代码
@app.before_first_request
def beforefirst():
print("我是第一次请求之前调用的")
@app.before_request
def before():
print("我是每次请求都调用的")
@app.after_request
def after(params):
print("after_request")
@app.teardown_request
def teardown():
print("不管异常不异常,我都是每次都执行")
模板
- 模板就是定义在template中的html文件
jinja2语法
{%... %} Jinja语句,例如判断、循环语句
{{... }} 变量,会显示在浏览器中
{#... #}注释,不会输出到浏览器中
变量规则
- {{ name }} 结构表示一个变量,它是一种特殊的占位符
变量过滤器
过滤符 | 描述 |
---|---|
safe | 渲染值时不转义 |
capitalize | 把值的首字母转换成大写,其他字母转换成小写 |
lower | 把值转换成小写形式 |
upper | 把值转换成大写形式 |
title | 把值中每个单词的首字母都转换成大写 |
trim | 把值的首尾空格去掉 |
striptags | 渲染之前把值中所有的 HTML 标签都删掉 |
变量过滤器代码
- {{ name | capitalize | ... }}
- 可以叠加
if语句
{% if name %}
hello,{{name}}
{% else %}
hello world
{% endif %}
for循环
<ol>
{% for a in range(10) %}
<li>{{a}}</li>
{% endfor %}
</ol>
定义函数(宏:macro)
{% macro myprint(A) %}
this is {{ A }}
{% endmacro %}
{{ myprint(A) }}
导入引用函数(需要调用执行)
{% from "abc.html" import func1 %}
{{ func1(A) }}
导入代码片段(不需要调用会自动执行)
{% include 'macro.html' %}
@app.route('/include/<a>')
def includetemplate(a):
return render_template('include.html',A = a)
-------------------
macro中的代码需要在很多地方执行到,那就用include,只要include了,那么里面的代码就会执行