flask的简单使用
1 flask介绍
#1 python 界的web框架
-Django:大而全,你要的东西都有 [orm,缓存,认证]
django-ninja
-flask:小而精,所有web开发需要的东西,借助于第三方集成
-web.py
-----同步框架--进程线程架构--3.x以后支持异步--
tornado
sanic
fastapi:高性能小而精,借助于第三方:orm
- Starlette 和 Pydantic
----异步框架--协程架构-----性能高
1.1 Werkzeug介绍
Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等
1.2 wsgiref 介绍
最简单的Web应用就是先把HTML用文件保存好,用一个现成的HTTP服务器软件,接收用户请求,从文件中读取HTML,返回。
如果要动态生成HTML,就需要把上述步骤自己来实现。不过,接受HTTP请求、解析HTTP请求、发送HTTP响应都是苦力活,如果我们自己来写这些底层代码,还没开始写动态HTML呢,就得花个把月去读HTTP规范。
正确的做法是底层代码由专门的服务器软件实现,我们用Python专注于生成HTML文档。因为我们不希望接触到TCP连接、HTTP原始请求和响应格式,所以,需要一个统一的接口协议来实现这样的服务器软件,让我们专心用Python编写Web业务。这个接口就是WSGI:Web Server Gateway Interface。而wsgiref模块就是python基于wsgi协议开发的服务模块
from wsgiref.simple_server import make_server
def mya(environ, start_response):
print(environ)
start_response('200 OK', [('Content-Type', 'text/html')])
if environ.get('PATH_INFO') == '/index':
with open('index.html','rb') as f:
data=f.read()
elif environ.get('PATH_INFO') == '/login':
with open('login.html', 'rb') as f:
data = f.read()
else:
data=b'<h1>Hello, web!</h1>'
return [data]
if __name__ == '__main__':
myserver = make_server('', 8011, mya)
print('监听8010')
myserver.serve_forever()
1.3 Jinja2 介绍
Jinja 是一个快速、富有表现力、可扩展的模板引擎。模板中的特殊占位符允许编写类似于 Python 语法的代码。然后向模板传递数据以渲染最终文档
# https://jinja.palletsprojects.com/en/3.1.x/
1.4 click介绍(django中得命令)
Click 是一个 Python 包,用于以可组合的方式使用尽可能少的代码创建漂亮的命令行界面。它是“命令行界面创建工具包”。它具有高度可配置性,但具有开箱即用的合理默认值
它的目的是使编写命令行工具的过程变得快速而有趣,同时也防止因无法实现预期的 CLI API 而造成的任何挫败感
# 3 Click in three points:
arbitrary nesting of commands
automatic help page generation
supports lazy loading of subcommands at runtime
Click三点:
命令的任意嵌套
自动生成帮助页面
支持运行时延迟加载子命令
https://click.palletsprojects.com/en/8.1.x/
# pip3 install click
import click
@click.command()
@click.option('--count', default=1, help='Number of greetings.')
@click.option('--name', prompt='Your name',help='The person to greet.')
def hello(count, name):
for x in range(count):
click.echo(f"Hello {name}!")
if __name__ == '__main__':
hello()
# 1 python3 app.py --count=3
# 2 python3 app.py --help
# 3 python3 app.py --count=3 --name=lqz
2 flask创建和运行
2.1 python-dotenv
# pip3 install python-dotenv
import os
from dotenv import load_dotenv
from dotenv import dotenv_values
## 1 加载配置文件
# 必须在根路径下新建一个 .env 的文件,并写入配置才能返回True,会把.env下的配置文件设置进环境变量
res=load_dotenv() # take environment variables from .env
print(res)
print(os.environ.get('DOMAIN'))
# You will probably want to add .env to your .gitignore, especially if it contains secrets like a password.
## 2 获取环境变量字典
config = dotenv_values(".env")
print(config)
print(config.get('DOMAIN'))
2.2 watchdog
# pip3 install watchdog
# 当前目录下文件修改会被监控到,打印日志
import sys
import time
import logging
from watchdog.observers import Observer
from watchdog.events import LoggingEventHandler
if __name__ == "__main__":
logging.basicConfig(level=logging.INFO,
format='%(asctime)s - %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
path = sys.argv[1] if len(sys.argv) > 1 else '.'
event_handler = LoggingEventHandler()
observer = Observer()
observer.schedule(event_handler, path, recursive=True)
observer.start()
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
observer.stop()
observer.join()
2.3 python内置虚拟环境
Use a virtual environment to manage the dependencies for your project, both in development and in production.
# 在开发和生产中,使用虚拟环境来管理项目的依赖关系
# 虚拟环境解决什么问题?您拥有的 Python 项目越多,您就越有可能需要使用不同版本的 Python 库,甚至是 Python 本身。一个项目的较新版本的库可能会破坏另一项目的兼容性。
# 虚拟环境是一组独立的 Python 库,每个项目对应一个。为一个项目安装的软件包不会影响其他项目或操作系统的软件包
Python comes bundled with the venv module to create virtual environments.
# Python 使用 venv 模块来创建虚拟环境
3.2.1 Mac/linux
# 创建虚拟环境
mkdir myproject
cd myproject
python3 -m venv .venv
# 激活虚拟环境
. .venv/bin/activate
3.2.2 Win
# 创建虚拟环境
mkdir myproject
cd myproject
py -3 -m venv .venv
# 激活虚拟环境
.venv\Scripts\activate
2.4 安装
pip install Flask
3 快速入门
3.1 多种方式运行flask
from flask import Flask
app=Flask(__name__)
# 配置路由和视图函数对应关系--》基于装饰器
# @app.route('/',methods=['GET'])
@app.get('/')
def index():
return 'hello flask'
if __name__ == '__main__':
app.run()
###### 运行flask项目的几种方式
# 方式一: python -m flask --app 6-第一个flask run
# 方式二: flask --app 6-第一个flask run
# 方式三: flask run --host=0.0.0.0 # py文件必须叫app.py
# flask --app hello run --debug
# 方式四:使用pycharm快速运行 配置一个 flaskserver
# 方式五:直接右键运行,必须加入如下代码
if __name__ == '__main__':
app.run()
# 运行当前项目
python -m flask --app hello run
# 或者
flask --app hello run
flask run --host=0.0.0.0
'''
3.2 debug 模式
# 运行时,开启debug模式
flask --app hello run --debug
# debug模式
-自动重启
-错误提示
3 fastapi 快速使用
- pip install fastapi
# 异步框架
from fastapi import FastAPI
from pydantic import BaseModel
app=FastAPI()
class Item(BaseModel):
name: str
age:int
@app.get('/')
async def index():
return {'code':100,'msg':'成功'}
@app.post('/login')
async def login(item:Item):
print(item.name)
print(item.age)
return item
if __name__ == '__main__':
import uvicorn
uvicorn.run(app='7-第一个fastapi:app',port=8001)
#name_app = os.path.splitext(os.path.basename(__file__))[0]
#uvicorn.run(app=f"{name_app}:app", port=8000)
4 显示用户案例
''' 学到的
1 返回新手四件套
- 返回字符串--》return '字符串'
- 返回模板--》render_template('detail.html',info=user)
- 返回重定向--》redirect('/login')
- 返回json--》jsonify({'code':100,'msg':'成功'})
2 request对象,是全局的--》from flask import request
-request.path
-request.method
.... 有很多,不展开讲--》记django的request---》类似
3 前端传入的:请求体 请求参数
-请求体:request.form--->编码格式是 urlencoded
-请求参数:request.args-->路径后的 /demo01?name=lqz&age=19
4 渲染 模板--》跟django 90%---》它比django更强大--》可以加括号--》字典可以.get []
for {{}}
5 session 使用
- 设置 app.secret_key='adsfa33w9SAD##@sdr434l'
- 设置值:session['username']
- 取值:session.get('username')
6 路由转换器
@app.route('/detail/<int:pk>', methods=['GET'])
'''
4.1 app.py
from flask import Flask, render_template, request, redirect, session,jsonify
app = Flask(__name__, template_folder="templates", static_folder="static")
app.secret_key='adsfa33w9SAD##@sdr434l' #如果使用session,必须加秘钥
# 用户信息
USERS = {
1: {'name': '刘亦菲', 'age': 18, 'gender': '男', 'text': "刘亦菲,1987年8月25日出生于湖北省武汉市,华语影视女演员、歌手,毕业于北京电影学院2002级表演系本科",'img':'https://img2.woyaogexing.com/2021/10/16/e3ccba623848430ba83209c0621a2256!400x400.jpeg'},
2: {'name': '彭于晏', 'age': 28, 'gender': '男', 'text': "彭于晏,1982年3月24日出生于中国台湾省澎湖县,毕业于不列颠哥伦比亚大学,华语影视男演员。。。。。。。。",'img':'https://img2.woyaogexing.com/2021/10/16/e71aa35728c34313bccb4c371192990f!400x400.jpeg'},
3: {'name': '迪丽热巴', 'age': 38, 'gender': '女', 'text': "迪丽热巴(Dilraba),1992年6月3日出生于中国新疆乌鲁木齐市,毕业于上海戏剧学院,中国内地影视女演员",'img':'https://img2.woyaogexing.com/2021/10/30/6a34146dde2d4f1c832463a5be1ed027!400x400.jpeg'},
4: {'name': '亚瑟', 'age': 38, 'gender': '男', 'text': "亚瑟,是腾讯手游《王者荣耀》中一名战士型英雄角色,也是《王者荣耀》的新手英雄之一,既可攻又可守",'img':'https://img2.woyaogexing.com/2021/10/30/371b2aa7a03c4f53b7b1bc86f877d7d1!400x400.jpeg'},
}
@app.route('/')
def index():
# 7 判断用户是否登录,如果登录了,返回模板
if session.get('username'):
# 1 返回模板,渲染到模板中
return render_template('index.html',user_dict=USERS)
# 如果没登录,重定向到login
else:
return redirect('/login')
@app.route('/login', methods=['GET', 'POST'])
def login():
# 2 判断是get请求还是post请求,需要使用request对象
## 2.1 request 正常每次请求都是新的request---》现在flask中全局就一个request--》它会不会乱套?
if request.method == 'GET':
return render_template('login.html')
else:
# 3 取出用户名密码--》请求对象中取--》request
username = request.form.get('username')
password = request.form.get('password')
if username == 'lqz' and password == '123':
# 6 登录成功--》登录信息写入cookie--》使用session写入
session['username'] = username
# 4 登录成功--》重定向到 index
return redirect('/')
else:
# 5 登录失败--》返回login.html 页面,但是页面中渲染错误信息
return render_template('login.html', error='用户名密码错误')
@app.route('/detail/<int:pk>', methods=['GET'])
def detail(pk):
if session.get('username'):
user = USERS.get(pk)
return render_template('detail.html',info=user)
else:
return redirect('/login')
@app.route('/demo01', methods=['GET'])
def demo01():
request.args
return jsonify({'code':100,'msg':'成功'})
if __name__ == '__main__':
app.run()
4.2 index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<title>Title</title>
</head>
<body>
<div class="container">
<!-- 头部-->
<div class="sticky-top">
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom">
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
<svg class="bi me-2" width="40" height="32">
<use xlink:href="#bootstrap"></use>
</svg>
<span class="fs-4">交友平台</span>
</a>
<ul class="nav nav-pills">
<li class="nav-item"><a href="#" class="nav-link active" aria-current="page">首页</a></li>
<li class="nav-item"><a href="#" class="nav-link">女生</a></li>
<li class="nav-item"><a href="#" class="nav-link">男生</a></li>
<li class="nav-item"><a href="#" class="nav-link">国产</a></li>
<li class="nav-item"><a href="#" class="nav-link">欧美</a></li>
</ul>
</header>
</div>
<!--轮播图-->
<div>
<div class="bd-example-snippet bd-code-snippet">
<div class="bd-example">
<div id="carouselExampleCaptions" class="carousel slide" data-bs-ride="carousel">
<div class="carousel-indicators">
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="0" class=""
aria-label="Slide 1"></button>
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="1"
aria-label="Slide 2" class="active" aria-current="true"></button>
<button type="button" data-bs-target="#carouselExampleCaptions" data-bs-slide-to="2"
aria-label="Slide 3" class=""></button>
</div>
<div class="carousel-inner">
<div class="carousel-item">
<img src="https://img.zcool.cn/community/01fb5458fedf57a801214550f9677a.jpg@2o.jpg" alt=""
width="100%" height="300">
<div class="carousel-caption d-none d-md-block">
<h5>激情绿荫</h5>
<p>Some representative placeholder content for the first slide.</p>
</div>
</div>
<div class="carousel-item active">
<img src="https://img2.baidu.com/it/u=2951612437,4135887500&fm=253&fmt=auto&app=138&f=JPEG"
alt="" width="100%" height="300">
<div class="carousel-caption d-none d-md-block">
<h5>品牌雨伞</h5>
<p>Some representative placeholder content for the second slide.</p>
</div>
</div>
<div class="carousel-item">
<img src="https://img1.baidu.com/it/u=1417689082,3333220267&fm=253&fmt=auto&app=138&f=JPEG"
alt="" width="100%" height="300">
<div class="carousel-caption d-none d-md-block">
<h5>家装节</h5>
<p>Some representative placeholder content for the third slide.</p>
</div>
</div>
</div>
<button class="carousel-control-prev" type="button" data-bs-target="#carouselExampleCaptions"
data-bs-slide="prev">
<span class="carousel-control-prev-icon" aria-hidden="true"></span>
<span class="visually-hidden">Previous</span>
</button>
<button class="carousel-control-next" type="button" data-bs-target="#carouselExampleCaptions"
data-bs-slide="next">
<span class="carousel-control-next-icon" aria-hidden="true"></span>
<span class="visually-hidden">Next</span>
</button>
</div>
</div>
</div>
</div>
<!-- 内容-->
<div class="row row-cols-md-2" style="padding: 10px">
{% for k,v in user_dict.items() %}
<div class="card">
<div class="row " style="padding: 10px">
<img src="{{v.get('img')}}" alt="" class="col-md-4">
<div class="col-md-8">
<div class="card-body">
<h5 class="card-title">{{v['name']}}</h5>
<p class="card-text">性别:{{v.gender}}</p>
<p class="card-text">年龄:{{v.age}}</p>
<p class="card-text">
<a href="/detail/{{k}}" class="btn btn-danger">查看详细</a>
</p>
</div>
</div>
</div>
</div>
{%endfor%}
</div>
<!-- table-->
<div class="bd-example" style="margin-top: 30px">
<table class="table table-hover table-striped table-bordered">
<thead>
<tr class="table-danger">
<th colspan="3" class="text-center">更多交友</th>
</tr>
</thead>
<tbody>
<tr class="table-success">
<th>杨幂</th>
<td>女</td>
<td>33</td>
</tr>
<tr class="table-warning">
<th scope="row">刘亦菲</th>
<td>未知</td>
<td>40</td>
</tr>
<tr class="table-success">
<th scope="row">彭于晏</th>
<td>男</td>
<td>23</td>
</tr>
<tr class="table-warning">
<th scope="row">陈奕迅</th>
<td>男</td>
<td>44</td>
</tr>
<tr class="table-success">
<th scope="row">薛之谦</th>
<td>男</td>
<td>36</td>
</tr>
<tr class="table-warning">
<th>李清照</th>
<td>女</td>
<td>未知</td>
</tr>
</tbody>
</table>
</div>
<!--分页-->
<div class="d-flex justify-content-center">
<ul class="pagination pagination-lg">
<li class="page-item">
<a class="page-link" href="#" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li class="page-item"><a class="page-link" href="#">1</a></li>
<li class="page-item"><a class="page-link" href="#">2</a></li>
<li class="page-item"><a class="page-link" href="#">3</a></li>
<li class="page-item"><a class="page-link" href="#">4</a></li>
<li class="page-item"><a class="page-link" href="#">5</a></li>
<li class="page-item"><a class="page-link" href="#">6</a></li>
<li class="page-item">
<a class="page-link" href="#" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</div>
<!-- 尾部-->
<div>
<footer class="py-3 my-4">
<ul class="nav justify-content-center border-bottom pb-3 mb-3">
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">首页</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">特性</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">联系我们</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">资料获取</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">关于</a></li>
</ul>
<p class="text-center text-muted">Copyright © 1998 - 2029 liuqingzheng. All Rights Reserved. </p>
</footer>
</div>
</div>
</body>
</html>
4.3 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css">
<title>登录</title>
</head>
<body>
<div class="container col-xl-10 col-xxl-8 px-4 py-5">
<div class="row align-items-center g-lg-5 py-5">
<div class="col-lg-7 text-center text-lg-start">
<h1 class="display-4 fw-bold lh-1 mb-3">亚洲最大交友平台</h1>
<p class="col-lg-10 fs-4">Bootstrap是Twitter推出的一个用于前端开发的开源工具包。它由Twitter的设计师Mark
Otto和Jacob Thornton合作开发,是一个CSS/HTML框架。目前,Bootstrap最新版本为5.0</p>
</div>
<div class="col-md-10 mx-auto col-lg-5">
<form class="p-4 p-md-5 border rounded-3 bg-light" method="post">
<div class="form-floating mb-3">
<input type="text" class="form-control" id="floatingInput" placeholder="name@example.com" name="username">
<label for="floatingInput">用户名</label>
</div>
<div class="form-floating mb-3">
<input type="password" class="form-control" id="floatingPassword" placeholder="Password" name="password">
<label for="floatingPassword">密码</label>
</div>
<div class="checkbox mb-3">
<label>
<input type="checkbox" value="remember-me"> 记住密码
</label>
</div>
<button class="w-100 btn btn-lg btn-primary" type="submit">登录</button>
<hr class="my-4">
<small class="text-muted">{{error}}</small>
</form>
</div>
</div>
</div>
</body>
</html>
4.4 detai.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css">
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<title>Title</title>
</head>
<body>
<div class="container">
<div class="sticky-top">
<header class="d-flex flex-wrap justify-content-center py-3 mb-4 border-bottom">
<a href="/" class="d-flex align-items-center mb-3 mb-md-0 me-md-auto text-dark text-decoration-none">
<svg class="bi me-2" width="40" height="32">
<use xlink:href="#bootstrap"></use>
</svg>
<span class="fs-4">交友平台</span>
</a>
<ul class="nav nav-pills">
<li class="nav-item"><a href="#" class="nav-link active" aria-current="page">首页</a></li>
<li class="nav-item"><a href="#" class="nav-link">女生</a></li>
<li class="nav-item"><a href="#" class="nav-link">男生</a></li>
<li class="nav-item"><a href="#" class="nav-link">国产</a></li>
<li class="nav-item"><a href="#" class="nav-link">欧美</a></li>
</ul>
</header>
</div>
<div class="position-relative overflow-hidden p-3 p-md-5 m-md-3 text-center bg-light">
<div class="col-md-5 p-lg-5 mx-auto my-5">
<h1 class="display-4 fw-normal">{{info.name}}</h1>
<img src="{{info.img}}" alt=""
width="300px" height="300px" style="margin: 20px">
<p class="lead fw-normal">{{info.text}}</p>
<a class="btn btn-outline-secondary" href="#">收藏</a>
</div>
<div class="product-device shadow-sm d-none d-md-block"></div>
<div class="product-device product-device-2 shadow-sm d-none d-md-block"></div>
</div>
<div>
<footer class="py-3 my-4">
<ul class="nav justify-content-center border-bottom pb-3 mb-3">
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">首页</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">特性</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">联系我们</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">资料获取</a></li>
<li class="nav-item"><a href="#" class="nav-link px-2 text-muted">关于</a></li>
</ul>
<p class="text-center text-muted">Copyright © 1998 - 2029 liuqingzheng. All Rights Reserved. </p>
</footer>
</div>
</div>
</body>
</html>
4.5 登录认证装饰器
# 问题一:登录装饰器,放上还是下 放下面
# 问题二:每个路由有个别名【反向解析】--》这个别名如果不写--》会以函数名作为别名--》一旦加了登录认证装饰器,所有别名都变成了 inner
# 1 使用装饰器装饰装饰器 @wraps(func)
# 2 每个人都指定别名
from flask import Flask, render_template, request, redirect, session, jsonify
app = Flask(__name__, template_folder="templates", static_folder="static")
app.secret_key = 'adsfa33w9SAD##@sdr434l' # 如果使用session,必须加秘钥
from functools import wraps
# 用户登录,写个装饰器
def login_required(func):
# @wraps(func)
def inner(*args, **kw):
# 判断有没有登录
if session.get('username'):
res = func(*args, **kw)
return res
else:
return redirect('/login')
return inner
# 用户信息
USERS = {
1: {'name': '刘亦菲', 'age': 18, 'gender': '男', 'text': "刘亦菲,1987年8月25日出生于湖北省武汉市,华语影视女演员、歌手,毕业于北京电影学院2002级表演系本科",
'img': 'https://img2.woyaogexing.com/2021/10/16/e3ccba623848430ba83209c0621a2256!400x400.jpeg'},
2: {'name': '彭于晏', 'age': 28, 'gender': '男', 'text': "彭于晏,1982年3月24日出生于中国台湾省澎湖县,毕业于不列颠哥伦比亚大学,华语影视男演员。。。。。。。。",
'img': 'https://img2.woyaogexing.com/2021/10/16/e71aa35728c34313bccb4c371192990f!400x400.jpeg'},
3: {'name': '迪丽热巴', 'age': 38, 'gender': '女', 'text': "迪丽热巴(Dilraba),1992年6月3日出生于中国新疆乌鲁木齐市,毕业于上海戏剧学院,中国内地影视女演员",
'img': 'https://img2.woyaogexing.com/2021/10/30/6a34146dde2d4f1c832463a5be1ed027!400x400.jpeg'},
4: {'name': '亚瑟', 'age': 38, 'gender': '男', 'text': "亚瑟,是腾讯手游《王者荣耀》中一名战士型英雄角色,也是《王者荣耀》的新手英雄之一,既可攻又可守",
'img': 'https://img2.woyaogexing.com/2021/10/30/371b2aa7a03c4f53b7b1bc86f877d7d1!400x400.jpeg'},
}
# 问题一:登录装饰器,放上还是下 放下面
# 问题二:每个路由有个别名【反向解析】--》这个别名如果不写--》会以函数名作为别名--》一旦加了登录认证装饰器,所有别名都变成了 inner
# 1 使用装饰器装饰装饰器 @wraps(func)
# 2 每个人都指定别名
@app.route('/',endpoint='index')
@login_required
def index():
return render_template('index.html', user_dict=USERS)
@app.route('/login', methods=['GET', 'POST'])
def login():
# 2 判断是get请求还是post请求,需要使用request对象
## 2.1 request 正常每次请求都是新的request---》现在flask中全局就一个request--》它会不会乱套?
if request.method == 'GET':
return render_template('login.html')
else:
# 3 取出用户名密码--》请求对象中取--》request
username = request.form.get('username')
password = request.form.get('password')
if username == 'lqz' and password == '123':
# 6 登录成功--》登录信息写入cookie--》使用session写入
session['username'] = username
# 4 登录成功--》重定向到 index
return redirect('/')
else:
# 5 登录失败--》返回login.html 页面,但是页面中渲染错误信息
return render_template('login.html', error='用户名密码错误')
@app.route('/detail/<int:pk>', methods=['GET'],endpoint='detail')
@login_required
def detail(pk):
user = USERS.get(pk)
return render_template('detail.html', info=user)
@app.route('/demo01', methods=['GET'])
def demo01():
request.args
return jsonify({'code': 100, 'msg': '成功'})
if __name__ == '__main__':
app.run()
5 flask的配置文件
# 1 django中配置文件用的是: settings.py
-实际开发中用了两套配置文件
# 2 flask配置文件使用--之 默认配置项- -debug --SECRET_KEY
print(app.config)
flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
{
'DEBUG': get_debug_flag(default=False), 是否开启Debug模式
'TESTING': False, 是否开启测试模式
'PROPAGATE_EXCEPTIONS': None,
'PRESERVE_CONTEXT_ON_EXCEPTION': None,
'SECRET_KEY': None,
'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
'USE_X_SENDFILE': False,
'LOGGER_NAME': None,
'LOGGER_HANDLER_POLICY': 'always',
'SERVER_NAME': None,
'APPLICATION_ROOT': None,
'SESSION_COOKIE_NAME': 'session',
'SESSION_COOKIE_DOMAIN': None,
'SESSION_COOKIE_PATH': None,
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'SESSION_REFRESH_EACH_REQUEST': True,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False,
'EXPLAIN_TEMPLATE_LOADING': False,
'PREFERRED_URL_SCHEME': 'http',
'JSON_AS_ASCII': True,
'JSON_SORT_KEYS': True,
'JSONIFY_PRETTYPRINT_REGULAR': True,
'JSONIFY_MIMETYPE': 'application/json',
'TEMPLATES_AUTO_RELOAD': None,
}
# 3 修改默认
# 方式一:直接在app上改,实际他们在config属性上(开发阶段用)
app.debug=True
app.secret_key='asdfasdf'
# 方式二:通过app.config改--》celery就是这样
app.config['DEBUG']=True
app.config['SECRET_KEY']='aaaa'
# 方式三:app.config.from_pyfile("python文件名称")--跟django一样
1 写一个 settings.py
2 app.config.from_pyfile('settings.py')
# 方式四:app.config.from_object('settings.TestingConfig')
class Config(object):
DEBUG = False
TESTING = False
DATABASE_URI = '127.0.0.1'
DATABASE_PORT = 3306
class ProductionConfig(Config):
DATABASE_URI = '192.168.1.11'
DATABASE_PORT = 3308
class DevelopmentConfig(Config):
DEBUG = True
# 方式其他:
app.config.from_envvar("环境变量名称")
app.config.from_json("json文件名称")
app.config.from_mapping({'DEBUG': True}) #可能会用
- 配置中心---》服务--》有个地址,发送请求会返回一对json格式配置文件
-nocos
# dotenv的使用
# 4 设置自己(跟修改默认一样)
-app.config['DB_PASSWORD']='lqz123'
6 路由系统
6.1基本使用装饰器
@app.route('/',methods=['GET'])
@app.get()
@app.post()
6.2 路由系统本质-->另一种写法
#1 使用的时候:@app.route('/',methods=['GET']) #--》decorator--》index=decorator(index)
def route(self, rule: str, **options: t.Any) -> t.Callable[[T_route], T_route]:
def decorator(f: T_route) -> T_route:
#1 如果没有传 endpoint ,就是None
endpoint = options.pop("endpoint", None)
#2 self 是 app对象,是Flask类的对象--》Flask类中得add_url_rule方法是路由的本质
self.add_url_rule(rule, endpoint, f, **options)
return f
return decorator
#2 于是,注册路由,我们可以不用装饰,自己写
app.add_url_rule('/index',endpoint=None,view_func=index,methods=['GET']) # 等同于django的path
6.3 route的参数,其实就是add_url_rule的参数
- rule, URL规则,路径
view_func, 视图函数名称
defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}-为函数提供参数 ---》django中也有,叫kwargs
endpoint = None, 名称[别名],用于反向生成URL,即: url_for('名称')
methods = None, 允许的请求方式,如:["GET", "POST"]
strict_slashes = None 对URL最后的 / 符号是否严格要求
```
@app.route('/index', strict_slashes=False)
#访问http://www.xx.com/index/ 或http://www.xx.com/index均可
@app.route('/index', strict_slashes=True)
#仅访问http://www.xx.com/index
```
redirect_to = None重定向到指定地址
@app.route('/index/<int:nid>', redirect_to='/home/<nid>')
#subdomain = None子域名访问
from flask import Flask
app = Flask(__name__)
app.debug=True
# @app.route('/')
def index(): # put application's code here
return 'Hello World!'
def login():
return 'login'
app.add_url_rule('/','index',index,methods=['GET'])
app.add_url_rule('/login','login',login)
if __name__ == '__main__':
app.run()
6.4转换器
# 4 转换器 app.add_url_rule('/index/<int:pk>')
DEFAULT_CONVERTERS = {
'default': UnicodeConverter,
'string': UnicodeConverter,
'any': AnyConverter,
'path': PathConverter,
'int': IntegerConverter,
'float': FloatConverter,
'uuid': UUIDConverter,
}