FastAPI 101
HST PF
自從轉成全職後端也已經快兩年了
現在的主要工作是寫Django
每天兢兢業業工作
偶爾寫寫Flask接案或賽project
那為什麼不都用Django寫?
Django
$ django-admin startproject steven5538
Flask
Django
$ django-admin startproject steven5538
$ cd steven5538
Flask
Django
$ django-admin startproject steven5538
$ cd steven5538
$ django-admin startapp FuckWorld
Flask
Django
$ django-admin startproject steven5538
$ cd steven5538
$ django-admin startapp FuckWorld
$ tree
Flask
Django
$ django-admin startproject steven5538
$ cd steven5538
$ django-admin startapp FuckWorld
$ tree
|-- FuckWorld
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
`-- manage.py
Flask
Django
$ django-admin startproject steven5538
$ cd steven5538
$ django-admin startapp FuckWorld
$ tree
|-- FuckWorld
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
`-- manage.py
$ cd FuckWorld; vim urls.py view.py; cd ..
Flask
Django
$ django-admin startproject steven5538
$ cd steven5538
$ django-admin startapp FuckWorld
$ tree
|-- FuckWorld
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
`-- manage.py
$ cd FuckWorld; vim urls.py view.py; cd ..
$ python manager.py runserver 0.0.0.0:5538
Flask
Django
$ django-admin startproject steven5538
$ cd steven5538
$ django-admin startapp FuckWorld
$ tree
|-- FuckWorld
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
`-- manage.py
$ cd FuckWorld; vim urls.py view.py; cd ..
$ python manager.py runserver 0.0.0.0:5538
Flask
$ vim steven5538.py
Django
$ django-admin startproject steven5538
$ cd steven5538
$ django-admin startapp FuckWorld
$ tree
|-- FuckWorld
| |-- __init__.py
| |-- settings.py
| |-- urls.py
| `-- wsgi.py
`-- manage.py
$ cd FuckWorld; vim urls.py view.py; cd ..
$ python manager.py runserver 0.0.0.0:5538
Flask
$ vim steven5538.py
$ python steven5538.py
來寫個傳統的Flask網頁
Steven5538.py
from flask import Flask, render_template
app = Flask()
@app.route('/index')
def index():
return render_template('index.html', name='steven5538')
index.html
<html>
<h1>Hello, {{name}}</h1>
</html>
但現在目前主流架構
都是前後端分離
後端工程師再也不用理前端的扣了
我們只要注意自己的API
剩下的都是前端的鍋 (誤
來看個Flask的API
Steven5538.py
from flask import Flask, request
app = Flask(__name__)
@app.route('/hacker', methods=['GET'])
def get_hacker():
info = request.json
name = info['name']
age = int(info['age'])
msg = f'駭客名字是:{name}'
return {'success': True, 'msg': msg, 'age':age}
import requests
data = requests.get('http://127.0.0.1:5538/hacker?name=steven5538&age=18').json()
print(data)
{ 'success': True, 'msg': '駭客名字是:steven5538', 'age': 18 }
唷, 看起來不錯喔
Steven5538.py
from flask import Flask, request
app = Flask(__name__)
@app.route('/hacker', methods=['GET'])
def get_hacker():
info = request.json
name = info['name']
age = int(info['age'])
msg = f'駭客名字是:{name}'
return {'success': True, 'msg': msg, 'age':age}
import requests
data = requests.get('http://127.0.0.1:5538/hacker?name=steven5538&age=十八').json()
print(data)
Steven5538.py
from flask import Flask, request
app = Flask(__name__)
@app.route('/hacker', methods=['GET'])
def get_hacker():
info = request.json
name = info['name']
age = int(info['age'])
msg = f'駭客名字是:{name}'
return {'success': True, 'msg': msg, 'age':age}
import requests
data = requests.get('http://127.0.0.1:5538/hacker?name=steven5538&age=十八').json()
print(data)
ValueError !!
哈Fix
Steven5538.py
from flask import Flask, request
app = Flask(__name__)
@app.route('/hacker', methods=['GET'])
def get_hacker():
info = request.json
name = info['name']
if not info['age'].isdigit():
return {'success': False, 'msg': '年齡必需整數'}
age = int(info['age'])
msg = f'駭客名字是:{name}'
return {'success': True, 'msg': msg, 'age':age}
import requests
data = requests.get('http://127.0.0.1:5538/hacker?name=steven5538&age=十八').json()
print(data)
{'success': False, 'msg': '年齡必需整數'}
Steven5538.py
import requests
data = requests.get('http://127.0.0.1:5538/hacker?age=18').json()
print(data)
from flask import Flask, request
app = Flask(__name__)
@app.route('/hacker', methods=['GET'])
def get_hacker():
info = request.json
name = info['name']
if not info['age'].isdigit():
return {'success': False, 'msg': '年齡必需整數'}
age = int(info['age'])
msg = f'駭客名字是:{name}'
return {'success': True, 'msg': msg, 'age':age}
Steven5538.py
import requests
data = requests.get('http://127.0.0.1:5538/hacker?age=18').json()
print(data)
from flask import Flask, request
app = Flask(__name__)
@app.route('/hacker', methods=['GET'])
def get_hacker():
info = request.json
name = info['name']
if not info['age'].isdigit():
return {'success': False, 'msg': '年齡必需整數'}
age = int(info['age'])
msg = f'駭客名字是:{name}'
return {'success': True, 'msg': msg, 'age':age}
KeyError !!
哈Fix
Steven5538.py
import requests
data = requests.get('http://127.0.0.1:5538/hacker?age=18').json()
print(data)
{'success': False, 'msg': '姓名不可為空'}
from flask import Flask, request
app = Flask(__name__)
@app.route('/hacker', methods=['GET'])
def get_hacker():
info = request.json
name = info.get('name', '')
if not name:
return {'success': False, 'msg': '姓名不可為空'}
if not info['age'].isdigit():
return {'success': False, 'msg': '年齡必需整數'}
age = int(info['age'])
msg = f'駭客名字是:{name}'
return {'success': True, 'msg': msg, 'age':age}
然後再來個300個endpoints
看來是可以開始準備退休生活了
但是為了明天的飯錢著想
還是要找個方法解決
終於在最近看到個好東西
Steven5538.py - by FastAPI
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Hacker(BaseModel):
name: str
age: int
@app.get('/hacker')
def get_hacker(hacker: Hacker):
return {'success': True, 'msg': f'駭客名字是:{hacker.name}', 'age':hacker.age}
import requests
data = requests.get('http://127.0.0.1:5538/hacker?name=steven5538&age=18').json()
print(data)
{ 'success': True, 'msg': '駭客名字是:steven5538', 'age': 18 }
Steven5538.py - by FastAPI
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Hacker(BaseModel):
name: str
age: int
@app.get('/hacker')
def get_hacker(hacker: Hacker):
return {'success': True, 'msg': f'駭客名字是:{hacker.name}', 'age':hacker.age}
import requests
data = requests.get('http://127.0.0.1:5538/hacker?name=steven5538&age=十八').json()
print(data)
{'detail': [{'loc': ['body','hacker', 'age'],
'msg':'value is not a valid integer',
'type':'type_error.integer'}]}
Steven5538.py - by FastAPI
import requests
data = requests.get('http://127.0.0.1:5538/hacker?age=18').json()
print(data)
{'detail': [{'loc': ['body','hacker', 'name'],
'msg':'filed required',
'type':'value_error.missing'}]}
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Hacker(BaseModel):
name: str
age: int
@app.get('/hacker')
def get_hacker(hacker: Hacker):
return {'success': True, 'msg': f'駭客名字是:{hacker.name}', 'age':hacker.age}
更多栗子
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
is_offer: bool = None
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
return {"item_name": item.name, "item_id": item_id}
更多栗子
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/model/{model_name}")
async def get_model(model_name: ModelName):
if model_name == ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
更多栗子
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str = None
price: float
tax: float = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
return item
<input>
{
"name": "Foo",
"description": "An optional description",
"price": 45.2,
"tax": 3.5
}
<output>
{
"name": "Foo",
"price": 45.2
}
更多栗子
from fastapi import Cookie, FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(*, ads_id: str = Cookie(None)):
return {"ads_id": ads_id}
from fastapi import FastAPI, Header
app = FastAPI()
@app.get("/items/")
async def read_items(*, user_agent: str = Header(None)):
return {"User-Agent": user_agent}
from fastapi import FastAPI, Form
app = FastAPI()
@app.post("/login/")
async def login(*, username: str = Form(...), password: str = Form(...)):
return {"username": username}
更多栗子
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class UserIn(BaseModel):
username: str
password: str
email: EmailStr
full_name: str = None
class UserOut(BaseModel):
username: str
email: EmailStr
full_name: str = None
@app.post("/user/", response_model=UserOut)
async def create_user(*, user: UserIn):
return user
更多栗子
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async def create_file(file: bytes = File(...)):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
return {"filename": file.filename}
更多栗子
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
# SQLALCHEMY_DATABASE_URL = "postgresql://user:password@postgresserver/db"
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()
更多栗子
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from sqlalchemy.orm import relationship
from .database import Base
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True)
hashed_password = Column(String)
is_active = Column(Boolean, default=True)
items = relationship("Item", back_populates="owner")
class Item(Base):
__tablename__ = "items"
id = Column(Integer, primary_key=True, index=True)
title = Column(String, index=True)
description = Column(String, index=True)
owner_id = Column(Integer, ForeignKey("users.id"))
owner = relationship("User", back_populates="items")
更多栗子
from fastapi import BackgroundTasks, FastAPI
app = FastAPI()
def write_notification(email: str, message=""):
with open("log.txt", mode="w") as email_file:
content = f"notification for {email}: {message}"
email_file.write(content)
@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):
background_tasks.add_task(write_notification, email, message="some notification")
return {"message": "Notification sent in the background"}
更多栗子
End Page
FastAPI 101
By iampf
FastAPI 101
- 1,104