python3 FastAPI框架入门 基本使用, 模版渲染, 数据交互,cookie使用, 上传文件, 静态文件配置

大爷来玩呀你懂得

[FastAPI框架入门 基本使用, 模版渲染, form表单数据交互, 上传文件, 静态文件配置]

安装

pip3 install fastapi                [all]
pip3 install unicorn
pip3 install aiofiles      
pip3 install HTMLResponse
pip3 install Response  
pip3 install shapely  
pip3 install starlette  
pip3 install requests  
pip3 install orjson                    # json 解析  
pip3 install jinja2                    #默认模板设置  
pip3 install python-multipart          #表单支持

基本使用(不能同时支持,get, post方法等要分开写)

@app.get('/') # 点get就支持get请求

    def read_root():

        return {"hello":'world'}

模版渲染

#!/usr/bin/python
# -*- coding:utf-8 -*-
import subprocess
import urllib.request
import platform
import socket,requests
import os, sys, json, datetime, time
import urllib.request

from fastapi.responses import HTMLResponse
from starlette.requests import Request
from starlette.responses import Response
from fastapi import FastAPI, Form
from fastapi import Cookie
from starlette.templating import Jinja2Templates
from starlette.staticfiles import StaticFiles

app = FastAPI()
templates = Jinja2Templates(directory="C:\\Users\\xxxx\\PycharmProjects\\FastAPI-kelan\\venv1")



@app.post("/user/")
async def create_cookie(request: Request, username: str = Form(...), password: str = Form(...)):
    print('username',username)
    print('password',password)
    if username=='admin' and password=='admin':
        return templates.TemplateResponse('index2.html', {'request': request, 'username': username})
    else:
        return {'status':'failed','username':username , 'password': password}


@app.get("/")
async def main(request: Request):
    return templates.TemplateResponse('login.html', {'request': request})

if __name__ == '__main__':
    import uvicorn

    uvicorn.run(app, host='192.168.120.26', port=8886)
index2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>hellokugou</h1>
</body>
</html>
login.html
<body>
        <div class="container">
            <form action="/user/" enctype="multipart/form-data" method="post">
                <label>Username</label>
                <br>
                <input name="username" type="username" >
                <br>
                <label>Password</label>
                <br>
                <input name="password" type="password" >
                <br><br>
                <input type="submit">
            </form>
        </div> <!-- /container -->
    </body>

fastapi本身是没有模版渲染功能的,需要你借助于第三方的模版工具

该框架默认情况下也是借助于jinja2来做模版渲染(flask也是使用jinja2, 如果用过flask, 默认是装过jinja2)

form表单数据交互&& cookie创建与使用

#!/usr/bin/python
# -*- coding:utf-8 -*-
import subprocess
import urllib.request
import platform
import socket,requests
import os, sys, json, datetime, time
import urllib.request

from fastapi.responses import HTMLResponse
from starlette.requests import Request
from starlette.responses import Response
from fastapi import FastAPI, Form
from fastapi import Cookie
from starlette.templating import Jinja2Templates
from starlette.staticfiles import StaticFiles

app = FastAPI()
templates = Jinja2Templates(directory="C:\\Users\\xxxx\\PycharmProjects\\FastAPI-kelan\\venv1")
project_list = [{'id':1,'project': 'sk_platform_furniture'},
{'id':21,'project': 'sk_service_data_process'}]
env_list = [{'id':2,'env':'sit'},{'id':3,'env':'uat'}]


@app.post("/user/")
async def create_cookie(request: Request, username: str = Form(...), password: str = Form(...)):
    print('username',username)
    print('password',password)
    if username=='admin' and password=='admin':
        obj = templates.TemplateResponse('index2.html', {'request': request, 'username': username})
        obj.set_cookie("dabaojian","nidongde",max_age=888)
        return obj
        #return templates.TemplateResponse('index2.html', {'request': request, 'username': username})
    else:
        return {'status':'failed','username':username , 'password': password}


@app.get("/")
async def main(request: Request):
    tk = request.cookies.get('dabaojian')
    print(tk, '---------------')
    if not tk:
        print('websocket@@@@@@@@@@@@@@env')
        return templates.TemplateResponse('login.html', {'request': request})
    else:
        return templates.TemplateResponse('index2.html', {'request': request})


@app.get("/websocket/")
async def read_project(request: Request):

    tk = request.cookies.get('dabaojian')
    print(tk,'---------------')
    if not tk:
        print( 'websocket@@@@@@@@@@@@@@env')
        return  templates.TemplateResponse('login.html', {'request': request})
    else:
        print({"success----------------------------------"})
        return templates.TemplateResponse('websocket_show2.html', {'request': request,'project_list':project_list,'env_list':env_list})


@app.post("/show_websocket/")
async def show_project(request: Request,projectname1: str = Form(...), envname1: str = Form(...)):
    print(projectname1,envname1,'######################show_websocket')
    tk = request.cookies.get('dabaojian')
    print(tk,'---------------')
    if not tk:
        print( 'shwo_logs@@@@@@@@@@@@@@env')
        return  templates.TemplateResponse('login.html', {'request': request})
    else:
        logs_an = {projectname1:envname1}
        print({"success----------------------------------"})
        return templates.TemplateResponse('websocket_show2.html', {'request': request,'logs_an':logs_an,'project_list':project_list,'env_list':env_list})

if __name__ == '__main__':
    import uvicorn

    uvicorn.run(app, host='192.168.120.26', port=8886)
index2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>hellokugou</h1>
    <div>
        <a href="/websocket/" class="btn btn-info"><font size="3" face="arial" color="#006400">websocket</font></a>
    </div>
</body>
</html>
show_websocket2.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <h1>show websocket</h1>
    <form method="POST" enctype="multipart/form-data" action="/show_websocket/">
        <p>
            项目名:
            <select name="projectname1">
                <option> 请选择项目 </option>
                {% for row in project_list %}
                <option>{{ row.project }}</option>
                {% endfor %}
            </select>
        </p>
        <p>
            环 境 :
            <select name="envname1">
                <option> 请选择环境 </option>
                {% for row in env_list %}
                <option>{{ row.env }}</option>
                {% endfor %}
            </select>
        </p>

        <input type="submit" value="提交" />
        <a href="/" class="btn btn-success" id="addModal"><font size="3" face="arial" color="#006400">home</font></a>
        <div>
            <textarea rows="28" cols="140" name="logstext"> {{logs_an}} </textarea>
        </div>
    <h2>不用乱点,其他功能都没加------------懒</h2>
</body>
</html>

注意: 如果要使用request.form()支持表单“解析”,则为必需 python-multipart 。

image.png

  • index

image.png

上传文件

from starlette.requests import Request
from fastapi import FastAPI, Form, File, UploadFile
from starlette.templating import Jinja2Templates
from typing import List
from starlette.staticfiles import StaticFiles


app = FastAPI()
# 挂载模板文件夹
tmp = Jinja2Templates(directory='C:\\Users\\xxxx\\PycharmProjects\\FastAPI-kelan\\venv1')
app.mount("/static", StaticFiles(directory="C:\\Users\\xxxx\\PycharmProjects\\FastAPI-kelan\\venv1\\static"), name="static")


@app.get('/')  # 接受get请求
async def get_file(request: Request):
    return tmp.TemplateResponse('file.html', {'request': request})

# 单个文件
@app.post('/one/')  
async def get_user(request: Request,
                   file: bytes = File(...),       # # 把文件对象转为bytes类型,这种类型的文件无法保存
                   file_obj: UploadFile = File(...),    # UploadFile转为文件对象,可以保存文件到本地
                   info: str = Form(...)    # 获取普通键值对
                   ):

    # 保存上传的文件
    contents = await file_obj.read()
    with open("/static/file/" + file_obj.filename, "wb") as f:
        f.write(contents)

    return tmp.TemplateResponse('upload.html', {
        'request': request,
        'file_size': len(file),
        'file_name': file_obj.filename,
        'info':info,
        'file_content_type':file_obj.content_type
    })

# 多个文件
@app.post('/more/')
async def get_files(request:Request,
                    files_list:List[bytes] = File(...),  # [使用二进制数据]
                    files_obj_list:List[UploadFile]=File(...)  # [file_obj1,file_obj2,....] #可以同时上传多个文件
                    ):

    # 保存上传的多个文件
    for file in files_obj_list:
        contents = await file.read()
        filename = file.filename
        with open("static/file/" + filename, "wb") as f:
            f.write(contents)

    return tmp.TemplateResponse('upload.html',
                                {'request':request,
                                 'file_sizes':[len(file) for file in files_list],
                                 'file_names':[file_obj.filename for file_obj in files_obj_list]
                                 }
                                )

if __name__ == '__main__':
    import uvicorn

    uvicorn.run(app, host='192.168.120.26', port=8886)
upload.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h2>单个文件</h2>
<h1>{{ file_size }}</h1>
<h1>{{ file_name }}</h1>
<h1>{{ info }}</h1>
<h1>{{ file_content_type }}</h1>

<h2>多个文件</h2>
<h1>{{ file_sizes }}</h1>
<h1>{{ file_names }}</h1>
</body>
</html>
file.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>单个文件</h1>
<form action="/one/" method="post" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="file" name="file_obj">
    <input type="text" name="info">
    <input type="submit">
</form>

<h1>多个文件</h1>
<form action="/more/" method="post" enctype="multipart/form-data">
    <input type="file" name="files_list" multiple>   {# multiple参数支持一次性传多个文件 #}
    <input type="file" name="files_obj_list" multiple>
    <input type="submit">
</form>
</body>
</html>

image.png

image.png

image.png

  • 上传文件-显示

image.png

  • 注意 file 目录需要提前创建

静态文件配置

1.使用 HTMLResponse 在python代码中体现html

@app.get("/logs/{Jenvironment}/{project}")
def read_project_logs(project: str,Jenvironment: str):
    print(project, '#######################project')
    print(Jenvironment, '@@@@@@@@@@@@@@env')
    #print(ansible_project_websocket_port(project,Jenvironment),"$$$ansible_project_websocket_port-LIst")

    html_content = """
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>config-center</title>
    </head>
    <body>
        <p>{tansiblestr}</p>
    </body>
    </html>
    """.format(tansiblestr=ansible_project_logs(project,Jenvironment))
    return HTMLResponse(content=html_content, status_code=200)


2.需要安装aiofiles模块

from starlette.staticfiles import StaticFiles


app = FastAPI()
app.mount("/static", StaticFiles(directory="C:\\Users\\xxxx\\PycharmProjects\\FastAPI-kelan\\venv1\\static"), name="static")
StaticFiles

image.png

image.png

layout.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
    <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css">
    <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css" >
    <link rel="stylesheet" href="/static/css/commons.css" >
    {% block css %}{% endblock %}

</head>
<body>
    <div class="pg-header">
        <div class="logo left">SEAN-Config_Center</div>
        <div class="avatar right" style="position: relative">
            <img style="width: 40px;height: 40px; " src="/static/images/12.jpg">
            <div class="user-info">
                <a>个人资料</a>
                <a>注销</a>
            </div>
        </div>
        <div class="rmenus right">
            <a><i class="fa fa-commenting" aria-hidden="true"></i>消息</a>
            <a><i class="fa fa-envelope-open" aria-hidden="true"></i>邮箱</a>
        </div>
    </div>
    <div class="pg-body">
        <div class="menus">
            <a> <i class="fa fa-television" aria-hidden="true"></i> 列表</a>
            <a> <i class="fa fa-plus" aria-hidden="true"></i> 添加</a>
            <a> <i class="fa fa-file-text" aria-hidden="true"></i> 生成</a>
            <a> <i class="fa fa-cog" aria-hidden="true"></i> 工具</a>
        </div>
        <div class="content">
            <ol class="breadcrumb">
                <li><a href="#">Home</a></li>
                <li><a href="#">Library</a></li>
                <li class="active">Data</li>
            </ol>
            {% block xx %}{% endblock %}

        </div>
    </div>
    {% block js %}{% endblock %}
</body>
</html>
当 staic目录设置之后,基本就和django 一样使用 bootstrap等等了。
阅读 2.5k

这个人很懒,没有什么说的。

72 声望
9 粉丝
0 条评论

这个人很懒,没有什么说的。

72 声望
9 粉丝
文章目录
宣传栏