本文由 简悦 SimpRead 转码, 原文地址 blog.csdn.net
Flask 框架的基础教程:
一、web 工作原理
1. B/S 和 C/S 架构
- B/S:浏览器/服务器架构(客户端需要更新才行)
- C/S:客户端/服务器架构(刷新页面即可更新)(可能会成为主流)
2. WEB 工作原理
客户端 > 服务器 > python(flask) > 数据库(mysql)
二、Flask 框架
1. 简介
- 是一个非常小的框架,可以称为微型框架,只提供了一个强劲的核心,其他的功能都需要使用拓展来实现。意味着可以根据自己的需求量身打造;
2. 组成
- 调试、路由、wsgi 系统
- 模板引擎 (Jinja2)
3. 安装
pip install flask
4. 简单使用
- 创建 Flask 框架。(社区版没有直接创建的功能,专业版有)
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__naem__)
# 视图函数(路由)
@app.route('/')
def index():
return '<h1>Hello Flask!<h1>'
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
app.run()
5. run 方法参数
参数 | 说明 | 默认值 |
---|---|---|
debug | 代码更新是否自动重启 | False |
theaded | 是否开启多线程 | False |
port | 指定端口 | 5000 |
host | 指定主机(设置 0.0.0.0 可以通过本地 IP 访问) | 127.0.0.1 |
6. 请求和响应
变量 | 上下文 | 描述 |
---|---|---|
current_app | 应用上下文 | 相当与在主程序中激活的实例化 app(app=Flask(__name__) ) |
g | 应用上下文 | 一次性函数,处理请求的临时变量。只在一个请求中被应用,下个请求开始时会自动重置 |
request | 请求上下文 | 请求对象。存放了客户端发来的 HTTP 信息 |
session | 请求上下文 | 记录用户和服务器之间的会话的。在服务器端记录需要记住的信息。(和 cookie 对应,cookies 是记录在客户端的) |
7. 请求钩子装饰器
函数 | 描述 |
---|---|
before_first_request | 第一次请求之前 |
before_request | 每次请求之前 |
app.after_request | 没有异常,每次请求结束后 |
app.teardown_request | 有异常也会运行,每次请求结束后 |
说明:以上钩子函数若写在蓝图中,只能针对蓝本的请求。若想在蓝本中设置全局有效的函数,需要使用带 app 的钩子函数。如:before_first_request 变为 before_app_first_request。
8. 视图函数
1. 不带参数的视图函数
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__name__)
# 视图函数(路由)
@app.route('/index')
def index():
return '<h1>Hello Flask!<h1>'
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
app.run()
2. 带参数的视图函数
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__name__)
# 视图函数(路由)
@app.route('/user/<username>')
def say_hello(username):
return '<h1>Hello %s !<h1>' % username
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
app.run()
- 参数要写在 <> 中、
- 视图函数的参数要与路由中的一致
- 也可以指定参数类型(int/float/path),默认是字符串
3. 带类型限定(path)的视图函数
# 导入Flask类库
from flask import Flask
# 创建应用实例
app = Flask(__name__)
# 视图函数(路由)
@app.route('/user/<path:info>')
def test(info):
return info
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
app.run()
前端运行结果:
- 路由中最后的 "/" 最好带上,否在访问时可能会报错。
9. 获取 request 请求值
# 导入Flask类库
from flask import Flask,request
# 创建应用实例
app = Flask(__name__)
# request
@app.route('/request/<path:info>')
def request_url(info):
# 完整的请求URL
return request.url
'''
url:127.0.0.1:5000/request/abc/def?username=xiaoming&pwd=123
网页返回值:http://127.0.0.1:5000/request/abc/def?username=xiaoming&pwd=123
'''
# 去掉GET参数的URL
return request.base_url
'''
网页返回值:http://127.0.0.1:5000/request/abc/def
'''
# 只有主机和端口的URL
return request.host_url
'''
网页返回值:http://127.0.0.1:5000/
'''
# 装饰器中写的路由地址
return request.path
'''
网页返回值:/request/abc/def
'''
# 请求方法类型
return request.method
'''
网页返回值:GET (也有可能时POST)
'''
# 远程地址
return request.remote_addr
'''
网页返回值:127.0.0.1:5000
'''
# 获取url参数
return request.args.get('username')
return request.args.get('pwd')
return str(request.args)
# 获取headers信息
return request.headers.get('User-Agent')
# 启动实施(只在当前模块运行)
if __name__ == '__main__':
app.run()
10. 响应的构造(make_response)
from flask import Flask,make_response
app = Flask(__name__)
@app.route('/response/')
def response():
# 不指定状态码,默认为200,表示OK
# return ‘OK’
# 构造一个404状态码
# 方法一
return 'not fount',404
# 方法二
# 导入make_response
# 自定义构造一个响应,然后返回200,构造也可以指定状态码404
res = make_response('我是通过函数构造的响应',404)
return res
if __name__ == '__main__':
app.run()
11. 重定向(redirect)
from flask import Flask,redirect
app = Flask(__name__)
@app.route('/old/)
def old():
# return '这里是原始内容。'
# 如果输入旧的old路由,会指向新的地址。
# 先输入一个外地请求试试
return redirect('https://www.baidu.com')
# 再输入一个本地请求试试
return redirect('/new/')
# 根据视图函数找到路由,指向方法:<url_for>中的参数'new'指向的是<函数名>
return redirect(url_for('new'))
return redirect(url_for('say_hello',username='xiaoming'))
@app.rout('/new/')
def new():
return '这里是新的内容'
if __name__ == '__main__':
app.run()
12. 终止 abort
from flask import Flask
app = Flask(__name__)
@app.route('/login/')
def login():
# return '欢迎登录'
# 此处使用abort可以主动抛出异常
abort(404)
if __name__ == '__main__':
app.run()
13. 会话控制 cookie 和 session(附加过期时间的设置)
1. 会话控制 cookie
# 发送到response的headers里面(客户端)
from flask import Flask
import time
app = Flask(__name__)
@app.route('/set_cookie/')
def set_cookie():
resp = make_response('设置cookie')
# 指定过期时间
expires = time.time + 10
resp.set_cookie('name','xiaoming',expires=expires)
return resp
if __name__ == '__main__':
app.run()
# 发送到request的headers里面(服务器)
# 如果清除cookie后,会导致name=xiaoming的cookie被清除。
# 那么就会在网页显示'你是哪个?'
from flask import Flask,request
app = Flask(__name__)
@app.route('/get_cookie/')
def get_cookie():
return request.cookie.get('name') or '你是哪个?'
if __name__ == '__main__':
app.run()
2. 会话控制 session
# 发送到response的headers里面(客户端)
from flask import Flask,session
import time,os
'''
这里可以给SECRET_KEY设置一个随机N位字符串:os.urandom(n)
'''
app = Flask(__name__)
# 设置一个随机18位字符串的密钥,也可以设置成固定字符串
app.config['SECRET_KEY'] = os.urandom(18)
# app.config['SECRET_KEY'] = '这是个密钥字符串'
@app.route('/set_session/')
def set_session():
# session本身是个字典,需要直接添加键值对
'''
添加session值之前,必须先设置SECRET_KEY
'''
session['username'] = 'xiaoqiao'
return 'session已设置'
@app.route('/get_session/')
def get_session():
# 获取session中的username的值,否则返回'who are you ?'
return session.get('username','who are you ?')
if __name__ == '__main__':
app.run()
14. 命令行控制启动
-
安装
pip install flask-script
-
使用
# 导入类库 from flask_script import Manager app = Flask(__name__) # 创建对象 manager = Manager(app) # 启动程序 if __name__ == '__main__': # app.run() # 命令行控制启动 manager.run()
-
参数:
启动:python manager.py runserver [-d] [-r] -? & --help 查看帮助 -d 开启调试模式 -r 修改文件自动加载 -h --host 指定主机 -p --port 指定端口 --threaded 使用多线程
-
详情参考:https://blog.csdn.net/weixin_45950544/article/details/104047350
15.Flask 模板
1. 模板介绍:
- 结构清晰、易于维护的代码开发原则是程序员追求的目标之一。目前我们所写的代码都比较简单,但是很明显的可以预见的一个问题是,当项目越来越复杂时,视图函数将变得异常庞大和繁琐,因为视图函数中存放了业务逻辑和表现逻辑。
- 解决这类问题的通用方法是将不同种类的逻辑分开存放:
- 业务逻辑:存放在视图函数中,专门处理用户的业务需求;
- 表现逻辑:存放在单独的模板文件夹中,负责表现效果。
2. 模板引擎
- 指定了一套特定的语法来实现表达逻辑,提供了一种专门的替换接口将模板文件换成目标文件(html)。——flask 中提供了专门的模板引擎(jinja2)
3. JinJa2(解析参数)
-
manager.py
from flask import Flask,render_template,render_template_string,g from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route('/index') def index(): # return '模板引擎测试' # 渲染模板文件 return render_template('index.html') @app.route('/index') def welcome('/index/<name>'): # 变量参数写在渲染函数的后面作为参数,前面的name是形参,后面的name是渲染模板中的解析内容 # return render_template('index.html',name=name) # 第二种方法,使用render_template_string(渲染字符串) # return render_template_string('<h2>hello {{ name }} ! <h2>',name=name) # 第三种方法,使用 g(全局函数),不需要分配就可以在模板中使用, # 只需要给定渲染模板即可; g.name = name return render_template('index.html') if __name__ == '__main__': manager.run()
-
templates(存放模板文件夹)/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> <h1>模板引擎测试</h1> { # {{ }} 括号中的内容将被解析 # } <h2> hello {{ name }} ! </h2> <h3> hello {{ g.name }} ! </h3> </body> </html>
4. 使用函数
- 在要解析的变量的后面添加一个‘ | ’
- 在‘ | ’的后面添加一个需要处理的函数
5. 常用函数
函数 | 说明 |
---|---|
capitalize | 首字母大写 |
upper | 全部大写 |
lower | 全部小写 |
title | 每个单词首字母大写 |
trim | 去掉两边的空白 |
striptags | 去掉所有的 HTML 标签 |
safe | 即删除标签,又保留标签功能 |
-
manager.py
from flask import Flask,render_template from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route('/index') def welcome('/index/<name>'): # 变量参数写在渲染函数的后面作为参数, # 前面的name是形参,后面的name是渲染模板中的解析内容 return render_template('index.html',name=name) if __name__ == '__main__': manager.run()
-
templates(存放模板文件夹)/index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> <h1>hello {{ name|capitalize }} ! </h1> </body> </html>
-
在网页上输入
127.0.0.1:5000/index/xiaoming
-
网页显示如下:
-
manager.py
from flask import Flask,render_template from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route(/usefunc/) def ues_func(): return render_template('use_func.html',var='hanmeimei') return render_template('use_func.html',var='<b>xiaoming</b>') if __name__ == '__main__': manager.run()
-
templates(存放模板文件夹)/use_func.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> <h1>hello {{ var|capitalize }} ! </h1> {# 将有<b>xiaoming</b>的标签删除 #} hello {{ var | striptags }} ! {# 即删除标签,又保留标签功能#} hello {{ var | safe }} ! </body> </html>
-
网页内容显示如下:
6. 控制结构
-
manager.py
from flask import Flask,render_template from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route(/control/) def control(): # 分配了该怎么处理,没有分配该怎么处理 return render_template('control.html',name='xiaoming') if __name__ == '__main__': manager.run()
-
templates(存放模板文件夹)/control.html
- if…else 语句
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> {# 判断显示内容 #} {# 如果分配了name的内容 #} {% if name %} <h1>hello {{ name|capitalize }} ! </h1> {# 如果不分配 #} {% else %} <h1>请登录</h1> {% endif %} </body> </html>
- for 语句
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> <ol> {% for x in range(1,5) %} {# 光显示 x 是不行的,因为没有进行解析。#} {# 需要对 x 进行解析,用{{ }} #} <li> {{ x }} </li> {% endfor %} </ol> </body> </html>
7. 宏的使用
-
基础使用方法:(类似于自定义函数)
-
manager.py
from flask import Flask,render_template from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route(/macro/) def macro(): return render_template('macro.html',name='xiaoming') if __name__ == '__main__': manager.run()
-
templates(存放模板文件夹)/macro.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> {# 这里是设置宏 #} {% macro show(name) %} <h1>This is {{name}}</h1> {% endmacro %} {# 下面是调用宏 #} {{ show(name) }} </body> </html>
-
-
集中定义宏并在其他文件中调用:(将宏单独存放在一个文件中)
-
manager.py(不变)
from flask import Flask,render_template from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route(/macro/) def macro(): return render_template('macro.html',name='xiaoming') if __name__ == '__main__': manager.run()
-
文件一:设置宏
templates(存放模板文件夹)/macro2.html{# 这里是设置宏 #} {% macro welcome(name) %} <h1>This is {{name}}</h1> {% endmacro %}
-
文件二:调用宏
templates(存放模板文件夹)/macro.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> {# 下面是调用宏 #} {% from 'macro2.html' import welcome %} {{ welcome(name) }} </body> </html>
-
8. 文件包含
-
manager.py
from flask import Flask,render_template from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route(/include/) def include(): return render_template('include.html',name='xiaowang') if __name__ == '__main__': manager.run()
-
文件一:设置宏
templates/macro2.html{# 这里是设置宏 #} {% macro welcome(name) %} <h1>This is {{name}}</h1> {% endmacro %}
-
文件二:调用宏
templates/macro.html<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>模板</title> </head> <body> {# 下面是调用宏 #} {% from 'macro2.html' import welcome %} {{ welcome(name) }} </body> </html>
-
文件三:收录方法 (类似拷贝文件)
templates/include.html{% include 'macro.html' %}
9. 模板继承
- 首先,要有一个父类模板;
- 然后,需要让子类模板继承父类模板;
- 最后,写一个测试的路由,渲染子类模板。
-
文件一:创建父类模板
templates/parents.html{# 写一个块(block) #} <html> <head> {% block head %} <title> {% block title %} 默认标题 {% endblock %} </title> {% endblock %} </head> <body> {% block body %} 默认内容 {% endblock %} </body> </html>
-
文件二:创建子类模板
templates/children.html- 继承父类模板,并可以在继承基础上重写父类
- 继承父类模板,保留原有父级模板中的内容
{# 继承自parents模板 #} {% extends 'parents.html' %} {# 指定块,重写父类 #} {% block title %}首页{% endblock %} {% block head %} {# 保留原有父级模板中的内容 #} {{ super }} <h1>添加的内容</h1> {% endblock %} {# 删除基础模板中的指定块 #} {% block body%} {% endblock %}
extends
方法与include
方法有所不同,include
方法照搬过来的时候,不能进行重写等操作,而extends
方法可以做到。 -
文件三:写一个测试的路由,渲染子类模板
manager.pyfrom flask import Flask,render_template from flask_script import Manager app = Flask(__name__) manager = Manager(app) @app.route(/extends/) def extends(): return render_template('children.html') if __name__ == '__main__': manager.run()
16. 使用 bootstrap(基础模板引用)
1. 安装
pip install bootstrap
2. 使用
-
bootstrap.py
from flask_bootstrap import Bootstrap app = Flask(__name__) bootstrap= Bootstrap(app) @app.route(/bootstrap/) def bootstrap(): return render_template('bootstrap.html',name='xiaoming') if __name__ == '__main__': manager.run()
-
templates/bootstrap.html
{# 继承自bootstrap的基础模板 #} {% extends 'bootstrap/base.html' %} {# 写标题 #} {% block title %}bootstrap测试{% endblock %} {# 写内容 #} {% block content %} <div class='container'> <h1>Hello {{name}} </h1> </div> {% endblock %}
-
bootstrap 的基础模板中定义了很多 block,可以在衍生模板中直接使用
块名 说明 doc 整个文档 html html 标签中的内容 head head 标签的内容 title title 标签的内容 body body 标签的内容 metas 一组 metas 标签 styles 层叠样式表 scripts 加载 Js 代码 content 自定义内容 navbar 定义导航条 说明:上述的 block 在子模板中都可直接使用,但是可能会出现覆盖问题,当出现问题时,很多时候都是因为没有调用 super()
3. 基础模板定制
- 继承 bootstrap, 自定义 base 模板
-
templates/base.html
{# 继承自bootstrap的基础模板 #} {% from bootstrap/base.html %} {% block title %}博客{% endblock %} {% block navbar %} <nav style='border-radius:0px;'> <div> <!-- Brand and toggle get grouped for better mobile display --> <div> <button type="button" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1" aria-expanded="false"> <span>Toggle navigation</span> <span></span> <span></span> <span></span> </button> <a href="#">首页</a> </div> <!-- Collect the nav links, forms, and other content for toggling --> <div> <ul> <li><a href="#">板块一</a></li> <li><a href="#">板块二</a></li> </ul> <ul> <li><a href="#">登录</a></li> <li><a href="#">注册</a></li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav> {% endblock %} {% block content %} <div class='container'> {% block page_content %} 默认内容 {% endblock %} </div> {% endblock %}
-
base.py
from flask_bootstrap import Bootstrap app = Flask(__name__) bootstrap= Bootstrap(app) @app.route('/') def base(): return render_template('base.html') if __name__ == '__main__': manager.run()
-
渲染效果:
4. 自定义错误页面
-
添加视图函数
@app.errorhandler(404): def page_not_found(e): return render_template('404.html')
-
创建模板文件:404.html
{# 继承自bootstrap的基础模板 #} {% extends 'bootstrap.html' %} {% block title %}出错了!{% endblock %} {% block page_content %}大哥,你是不是搞错了@_@{% endblock %}
Comments | NOTHING