一 flask简介,创建,运行以及安装,fastapi简单介绍
一 flask 创建和运行
1.flask介绍
1.1 python 中的web 框架
- 
django:大而全,使用率较高;
- django有很多内置app,缓存,信号,消息,权限,admin
 - https://github.com/django/django
 
 - 
flask:小而精,几乎没有内置,都需要用第三方解决
- 随着项目越来越大,使用第三方插件,越来越像django
 - https://github.com/pallets/flask
 
 - 
fastapi:异步框架,号称效率高,一般新项目使用
 - 
Sanic
 - 
Tornado
 - 
web.py ...
 
1.2 flask fastapi 跟django的异同
- 相同点:都是python的web框架
 - 不同点:
- 
django比较全面,web开发中使用到的东西,它都会内置
-orm
-forms组件,表单验证
-模板:dtl
-缓存
-信号
-admin 后台管理。。。 - 
flask小而精,只保留了web开发的核心功能,其他的需要借助于第三方实现
众多第三方,比如orm咱们会用sqlalchemy,peewee。 - 
fastapi:跟flask相似,只保留了web开发的核心功能,其他的需要借助于第三方实现
-异步框架
-更方便的使用python async 和 await 关键字来实现异步操作 
 - 
 
1.2 创建flask项目
- 使用pycharm创建


 - 在run.py中直接写
 
from flask import Flask,render_template
app = Flask(__name__)  # __name__这个参数必须传
# 路径
@app.route('/')
def index():
    return render_template('index.html')
if __name__ == '__main__':
    app.run()
#启动文件命令: flask --app 指定py文件名字 run   
1.3 flask
# 0 Flask是一个用Python编写的Web应用框架。它由Armin Ronacher开发,他领导着一个名为Pocco的国际Python爱好者团队。Flask基于Werkzeug WSGI工具包和Jinja2模板引擎。两者都是Pocco项目
# 1 Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,
即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器
# 2 “微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握
# 3 默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用
# 4 Flask depends on the Werkzeug WSGI toolkit, the Jinja template engine, and the Click CLI toolkit
    -Werkzeug WSGI:接收请求   django 中得 wsgiref
    -jinja2模板     :渲染模板的  django中得dtl
    -Click CLI      :命令定制工具   django 的 manage.py runserver/migrate...
2. Werkzeug WSGI-(socket服务端)
Werkzeug是一个WSGI工具包,他可以作为一个Web框架的底层库。这里稍微说一下, werkzeug 不是一个web服务器,也不是一个web框架,而是一个工具包,官方的介绍说是一个 WSGI 工具包,它可以作为一个 Web 框架的底层库,因为它封装好了很多 Web 框架的东西,例如 Request,Response 等等
Werkzeug is a comprehensive WSGI web application library. It began as a simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility libraries.
Werkzeug 是一个综合性 WSGI Web 应用程序库。它最初是 WSGI 应用程序的各种实用程序的简单集合,现已成为最先进的 WSGI 实用程序库之一。
Werkzeug doesn’t enforce any dependencies. It is up to the developer to choose a template engine, database adapter, and even how to handle requests
Werkzeug 不强制执行任何依赖关系。由开发人员选择模板引擎、数据库适配器,甚至如何处理请求
# 补充:
# django--->wsgiref ,uwsgi
# flask---->Werkzeug
# django或flask--》都需要有web服务器---》web服务器需要符合 wsgi协议
    -规定了,框架是一个可调用对象,请求来了,wsgi服务器调用这个对象的时候,会传入 两个参数environ,start_response
    -flask中能找到这两个参数,django中也能找到这两个参数
# 后期:
    测试django项目,使用wsgiref,上线djagno项目,使用uwsgi,gunicorn
    测试flask项目,使用werkzeug,上线djagno项目,使用uwsgi,gunicorn

# https://werkzeug.palletsprojects.com/en/3.0.x/
# 1 了解即可
# 写了一个可调用对象,可以使用符合wsig协议的web服务器来调用,执行它
# def application(environ, start_response):
#     start_response('200 OK', [('Content-Type', 'text/plain')])
#     return ['Hello World!'.encode('utf-8')]
# 2 使用符合wsgi协议的web服务器调用它
# from wsgiref.simple_server import make_server
#
# # 咱们这个application 函数---》它就是 django框架或flask框架
# # def application(environ, start_response):
# #     start_response('200 OK', [('Content-Type', 'text/plain')])
# #     return ['Hello World!'.encode('utf-8')]
# def application(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, application)
#     print('监听8011')
#     myserver.serve_forever()
### 3 使用werkzeug 运行 application
# 有了 Request和Response,路由分发,可以获取静态文件,可以返回html页面
from werkzeug.wrappers import Request, Response
from werkzeug.serving import run_simple
def application(environ, start_response):
    request = Request(environ)
    text = f"Hello {request.args.get('name', 'World')}!"
    response = Response(text, mimetype='text/plain')
    return response(environ, start_response)
if __name__ == '__main__':
    run_simple('localhost', 4000, application)
3. Jinja template engine
Jinja is a fast, expressive, extensible templating engine. Special placeholders in the template allow writing code similar to Python syntax. Then the template is passed data to render the final document
Jinja 是一个快速、富有表现力、可扩展的模板引擎。模板中的特殊占位符允许编写类似于 Python 语法的代码。然后向模板传递数据以渲染最终文档
# 语法完全支持 dtl,但比dtl更强大
# https://jinja.palletsprojects.com/en/3.1.x/
4. Click CLI
# flask 2 版本加入的--->定制命令的工具
	python manage.py init_db
    
# 介绍
# 1 Click is a Python package for creating beautiful command line interfaces in a composable way with as little code as necessary. It’s the “Command Line Interface Creation Kit”. It’s highly configurable but comes with sensible defaults out of the box
Click 是一个 Python 包,用于以可组合的方式使用尽可能少的代码创建漂亮的命令行界面。它是“命令行界面创建工具包”。它具有高度可配置性,但具有开箱即用的合理默认值
# 2  It aims to make the process of writing command line tools quick and fun while also preventing any frustration caused by the inability to implement an intended CLI API
它的目的是使编写命令行工具的过程变得快速而有趣,同时也防止因无法实现预期的 CLI API 而造成的任何挫败感
# 3  Click in three points:
  arbitrary nesting of commands	
  automatic help page generation
  supports lazy loading of subcommands at runtime 
Click三点:
  命令的任意嵌套
  自动生成帮助页面
  支持运行时延迟加载子命令
# pip3 install click
import click
@click.command()
@click.option('--count', default=1, help='打印次数')
@click.option('--name', prompt='你的名字',help='The person to greet.')
def hello(count, name):
    for x in range(count):
        print(f"Hello {name}!")
if __name__ == '__main__':
    hello()
# 1  python3 app.py --help
# 2  python3 app.py --count=4 --name=wrx
# 3  python3 app.py --count=4
使用命令: python 文件名 --help
结果:显示可以执行的命令

python3 app.py --count=4 --name=wrx

python 2.Click的使用.py --count=4

5.flask安装
# 最新flask 要python 3.8 以上
pip install flask   # 最新3.x
安装完成后,会在script目录下多flask.exe 命令,后期运行flask需要使用它
##### 必选依赖
Werkzeug :wsgi的工具包
Jinja:模板渲染
MarkupSafe :解决了xss攻击
ItsDangerous:加密解密的--->session会用到
Click:定制命令的
Blinker :信号会用到 signal
##### 可选依赖:这些依赖不会自动安装。如果您安装它们,Flask 将检测并使用它们
watchdog:监控文件的操作
python-dotenv:管理和配置python项目中的环境变量
5.1 watchdog使用
# 需要安装: pip 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()
结果:监控文件的操作

5.2 python-dotenv
# pip 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('MYSQL_HOST'))
# 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'))
总结:
python-dotenv的作用是从一个名为.env的文件中加载环境变量。这对于管理和配置Python项目中的环境变量非常有用。环境变量通常用于存储敏感信息,如API密钥、数据库凭据和其他配置设置。通过使用.env文件,开发人员可以将这些信息与其代码库分开,并轻松地管理不同环境(例如开发、测试、生产)的不同配置
6.虚拟环境
6.1虚拟环境介绍
Use a virtual environment to manage the dependencies for your project, both in development and in production.
# 在开发和生产中,使用虚拟环境来管理项目的依赖关系
What problem does a virtual environment solve? The more Python projects you have, the more likely it is that you need to work with different versions of Python libraries, or even Python itself. Newer versions of libraries for one project can break compatibility in another project.
# 虚拟环境解决什么问题?您拥有的 Python 项目越多,您就越有可能需要使用不同版本的 Python 库,甚至是 Python 本身。一个项目的较新版本的库可能会破坏另一项目的兼容性。
Virtual environments are independent groups of Python libraries, one for each project. Packages installed for one project will not affect other projects or the operating system’s packages.
# 虚拟环境是一组独立的 Python 库,每个项目对应一个。为一个项目安装的软件包不会影响其他项目或操作系统的软件包
Python comes bundled with the venv module to create virtual environments.
# Python 使用 venv 模块来创建虚拟环境
6.2 使用:venv 做为虚拟环境
方式一
# 创建虚拟环境
mkdir myproject
方式二
# 切换路径
cd myproject
# python 使用 venv模块来创建虚拟环境
py -3 -m venv .venv
# 激活虚拟环境
.venv\Scripts\activate

7.下载创建flask
# pip install flask
# 写个py文件,写入
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
    return 'hello world'
7.1运行项目方式
方式一(pycharm配置):
新建一个flask-server--->配置选中 script---target中选择要运行的文件

方式二 命令
    	1.flask app py文件名字 run(推荐)
        flask --app app.py run
    	2.python -m flask --app py文件名字 run
        python38 -m flask --app app.py run
        
        3.跟右键运行一样
    	python app.py
        
        4.少用(pip install python-dotenv)
    	flask app run  # app 是运行文件名
方式三:右键运行
     if __name__ == '__main__':
        app.run()

8.debug 模式
8.1 启动debug模式
# 方式一:使用命令
flask --app 文件名 run --debug
# 方式二:配置文件中勾选上FLASK_DEBUG
# 方式三:代码中加上app.debug=True
from flask import Flask
app = Flask(__name__)
app.debug=True
@app.route('/')
def index():
    raise Exception('报错')
    return 'hello world'
if __name__ == '__main__':
    app.run()
8.2 作用
- 浏览器显示错误信息
 - 自动重启
 
二 fastapi
## pip install fastapi
## pip install  
## 快速使用:
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
def read_root():
    return {'Hello':'World'}
## 如果有io
from fastapi import FastAPI
import asyncio
app = FastAPI()
@app.get("/")
async def read_root():
    # 如果有io
    await asyncio.sleep(2)
    return {"Hello": "World"}
## 在命令行中输入以下命令启动  uvicorn 6-fastapi快速体验:app
三 显示用户小案例
from flask import Flask,request,render_template,redirect,session
app = Flask(__name__)
app.debug=True
# 如果要使用session,必须加这一句
app.secret_key='adfggg-wang-rx'
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('/login',methods=['GET','POST'])
# 这里不用传入request,虽然request是全局的,但是在任意的视图函数中都不会乱,因为在flask中,request在哪里用就是哪里的request
def login():
    if request.method=='GET':
        return render_template('login.html')
    else:
        username = request.form.get('username')
        password = request.form .get('password')
        if username=='lqz'and password =='123':
            # 登录成功,要把登录信息写入到session中
            session['username']=username
            # 登录成功重定向到首页
            return redirect('/')
        else:
            return render_template('login.html',error='用户名或密码错误')
# 首页
@app.route('/',methods=['GET'])
def index():
    username = session.get('username')
    if username:
        return render_template('index.html',user_dict=USERS)
    else:
        return redirect('/login')
# 详情
@app.route('/detail/<int:pk>')
def detail(pk):
    user = USERS.get(pk)
    return render_template('detail.html',user=user)
templates/login.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form method="post">
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="password" name="password"></p>
    <p><input type="submit" value="登录"><span style="color: red">{{error}}</span></p>
</form>
</body>
</html>
templates/index.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{%for key,value in user_dict.items()%}
<p>用户id:{{key}}</p>
<p>用户名:{{value.name}}</p>
<p>用户年龄:{{value['age']}}</p>
<p>性别:{{value.get('gender')}}</p>
<p><a href="/detail/{{key}}">详情:</a></p>
<hr>
{%endfor%}
</body>
</html>
templates/detail.html:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<p>用户名:{{user.name}}</p>
<p>用户年龄:{{user.age}}</p>
<p>性别:{{user.gender}}</p>
<p>介绍:{{user.text}}</p>
<hr>
</body>
</html>
使用bootstrap进行页面美化
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</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>
点击查看代码
<!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.text}}</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>
点击查看代码
<!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">{{user.name}}</h1>
            <img src="{{user.img}}" alt=""
                 width="300px" height="300px" style="margin: 20px">
            <p class="lead fw-normal">{{user.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>
总结:
# 1 request是全局: request.method   request.path   
# 2 request.form  前端post提交的数据
# 3 request.args  前端get请求提交的数据
# 4 路由注册是使用装饰器
@app.route('/detail/<int:pk>')
def detail(pk):
# 5 路由有转换器:int 。。。。
/detail/<int:pk>
/detail/?pk=1
#6 新手四件套
    return '字符串'
    return render_template('index.html', user_dict=USERS)
    return redirect('/login')
    return jsonify(字典,列表)
    
# 7 session的使用--全局导入--必须加秘钥
    放值:session['key']=value
    取值:session.get('key')

                
            
        
浙公网安备 33010602011771号