教程
教程地址: 千锋教育Flask2框架从入门到精通,Python全栈开发必备教程
老师讲的很好,可以看一下。
项目拆分
项目结构
在项目根目录下,创建一个App
目录,这是项目下的一个应用,应该类似于后端的微服务,一个微服务算作一个应用。
在App
目录下创建static
目录,存放静态文件,也就是对应的css
、js
在App
目录下创建templates
目录,存放模板,也就是对应的html
。
如果只是拿来写后台不需要前端部分,上面这两个目录都可以不用创建。
在App
目录下创建__init__.py
,这是这个应用的初始化文件
在App
目录下创建models.py
,这是这个应用的模型与数据库文件
在App
目录下创建views.py
,这是这个应用的路由和视图函数
在项目根目录下创建app.py
,这是整个项目的启动文件。
__init__.py
# 初始化文件,创建Flask应用
from flask import Flask
from .views import blue
def create_app():
app = Flask(__name__)
# 注册蓝图
app.register_blueprint(blueprint=blue)
return app
models.py
# 存放模型、数据库
# 暂时为空的,后面使用
views.py
# 存放路由+视图函数
# 使用蓝图的方式来管理
from flask import Blueprint
# 引入模型
from .models import *
# 创建蓝图,名字可以随意定义
blue = Blueprint('user', __name__)
@blue.route('/')
def index():
return "index"
app.py
from App import create_app
app = create_app()
if __name__ == '__main__':
app.run(debug=True)
运行app.py
启动项目,项目启动成功,说明拆分没有问题。
上面的拆分使用到了蓝图
在Flask框架中,蓝图(Blueprint)是一种组织和管理路由的方式。它允许将应用程序分成一组相关的视图、模板和静态文件。通过蓝图,您可以将应用程序的功能模块化,使得代码更加清晰和可维护。
使用蓝图,您可以在应用程序中定义多个蓝图对象,每个蓝图对象都表示一个独立的模块。每个蓝图可以有自己的路由、视图函数、模板和静态文件。
通过将蓝图注册到应用程序中,可以将蓝图的功能集成到整个应用程序中。这样,您可以更好地组织和管理代码,使得不同模块之间的代码更加独立和可重用。
使用蓝图的一个常见场景是构建大型应用程序,其中有多个功能模块需要独立开发和维护。蓝图的优点是可以使得团队成员在不同模块上并行开发,同时保持代码的整洁和可扩展性。
请求与相应
请求
服务器在接收到客户端的请求后,会自动创建Request
对象,该对象由Flask框架创建,不允许修改。
常用属性
url 完整的请求地址
base_url 去掉get参数的url
host_usr 只有主机和端口号的url
path 路由中的路径
method 请求方式
remote_addr 请求的客户端地址
args get请求参数
form post请求参数
files 文件上传
headers 请求头
cookies 请求中的cookie
user_agent 用户代码,包括浏览器和操作系统,可以用于反爬虫
常用方法
# 获取get请求的参数,get请求会出现属性名相同的情况
request.args.get(属性名) 或 request.args.getlist(属性名)
# 获取post请求参数
request.form.get(属性名)
# 获取cookie
request.cookies.get(属性名)
响应
服务器想客户端返回的消息
响应的几种类型:字符串、模板渲染(常用于前后端不分离)、返回json数据(常用于前后端分离)、自定义Response对象
cookie
cookie
本身由浏览器保存,通过Response
将cookie
写到浏览器,下一次访问时,浏览器会根据不同的规则携带cookie
过来。常用于登录
特点
- 客户端会话技术,浏览器的会话技术
- 数据存储在客户端中
- 存储时使用键值对的结构进行存储
- 特性
- 支持过期时间
- 默认会自动携带本网站的所有cookie
- 根据域名进行cookie存储
- 不能跨浏览器
- cookie是通过服务器创建的response对象来创建的
设置cookie
response.set_cookie(key,value[,max_age=None,exprise=None])
max_age:整数,指定过期时间
exprise:整数,指定过期时间,可以指定一个具体的日期时间
两者只能选择一个
获取cookie
request.cookie.get(key)
删除cookie
response.delete_cookie(key)
基本流程
示例
登录界面 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>登录</title>
</head>
<body>
<h2>登录</h2>
<hr />
<!-- 使用视图函数访问,会自动解析成相应的路径 蓝图user下的login函数-->
<form action="{{url_for('user.login')}}" method="post">
<p>
用户名:<input type="text" name="username" />
</p>
<p>
密码:<input type="text" name="password" />
</p>
<p>
<button>提交</button>
</p>
</form>
</body>
</html>
首页home.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>首页</title>
</head>
<body>
<h2>首页</h2>
<hr />
{% if username %}
<p>欢迎用户:{{username}}</p>
{% endif %}
<!-- 路由跳转,使用定义好的路由地址 -->
<a href="/login/">登录</a>
</body>
</html>
路由和试图函数
# 双路由,访问/还是/home/,都会跳转到同一个页面
@blue.route("/")
@blue.route("/home/")
def index():
# 4、获取cookie,访问请求时会自动带上相应的cookie
username = request.cookies.get("username")
return render_template("home.html", username=username)
# 允许get、post两种请求方式
@blue.route("/login/", methods=["GET", "POST"])
def login():
# GET 访问登录页面
if request.method == "GET":
return render_template("login.html")
# POST 登录
elif request.method == "POST":
# 1、获取前端提交的表单数据
username = request.form.get("username")
password = request.form.get("password")
# 2、模拟登录
if username == "李四" and password == "123":
# 登录成功,跳转至首页
response = redirect(url_for("user.index"))
# 3、设置cookie
# response.set_cookie("username", username) # 默认浏览器关闭则cookie失效
response.set_cookie("username", username, max_age=3600 * 24 * 1) # 1天后过期
return response
else:
return "用户名或密码错误"
# 注销
@blue.route("/layout/")
def layout():
response = redirect(url_for("user.index"))
# 5删除cookie
response.delete_cookie("username")
return response
session
常用操作
设置密钥和过期时间
过期时间可以不设置,在关闭浏览器时自动清除。但是密钥必须设置,否则无法使用session
from App import create_app
from datetime import timedelta
app = create_app()
# 设置session密钥和过期时间
app.secret_key = "flask_onion"
app.permanent_session_lifetime = timedelta(minutes=60)
设置session
session['key'] = 'value'
获取session
session.get('key')
删除session
session.pop('key') # 删除某一个
session.clear() # 删除所有
cookie和session的区别
-
cookie
- 在浏览器存储
- 安全性较低
- 可以减轻服务器的压力
-
session
- 在服务器端存储
- 安全性高
- 对服务器要求较高
- 依赖cookie
模板语言
Flask中使用的模板引擎是Jinja2。Jinja2是一个现代的、功能强大的、基于Python的模板引擎,它允许开发人员在HTML模板中使用动态内容和逻辑控制结构。Jinja2提供了丰富的模板标签和过滤器,使得在Flask应用中生成动态内容变得非常简单和灵活。使用Jinja2,你可以在HTML模板中插入变量、循环、条件语句等,从而生成最终的HTML页面。Flask默认使用Jinja2作为模板引擎,你只需在Flask应用中创建模板文件,并在视图函数中使用render_template函数渲染模板即可。
变量的显示
@baseBlue.route("/")
def index():
data = {'name': '张三', 'age': 10}
return render_template("home.html", user=data)
<h1>姓名:{{ user.name }} 年龄:{{ user.age }}</h1>
if语句
<h2>
{% if user.age > 18 %} 你是大人
{% elif user.age>=6 %} 可以上学了
{% else %} 你是小孩
{% endif %}
</h2>
for循环
<ul>
{% for item in user.hobby %}
<li>{{item}}</li>
<li>
<!-- 使用loop可以获取下标,index是从1开始,index0是从0开始,除此之外loop还包含其他属性比如first、last -->
index: {{loop.index}} , index0: {{loop.index0}}
</li>
{% endfor %}
</ul>
block与extends标签
两者一般结合使用,block块标签,extends继承标签
# a.html
{% block content %}{% endblock %}
# b.html
{% extends 'a.html' %}{% block content %}
内容
{% endblock %}
- 可以理解为vue中的路由,
b.html
中的内容会在a.html
中的指定位置显示。但是flask中可以有多个块标签 content
是自己定义的,你也可以使用其他的比如aa
,但是必须保证一致- 可以多层嵌套继承,比如c继承b,b继承a
- 如果b中有
content
块,c中也存在content
块时最终会渲染c中的内容,如果想要保留b中的内容可以在c中使用{{ super() }}
include标签
可以用来加载其他的html内容
# a.html
<p>我是a.html中的内容</p>
# b.html,在b.html标签中加载a.html的内容(会加载所有内容)
{% include 'a.html' %}
宏定义
<!-- 宏定义 -->
{% macro show_name(name) %}
<p>{{name}}</p>
{% endmacro %}
<!-- 使用宏定义 -->
<h1>使用宏定义: {{show_name('这是宏定义')}}</h1>
宏定义的导入
宏定义,可以在模板中定义函数,在其他地方调用
{% from 'xxx' import aaa %}