Hướng dẫn này dùng cho môi trường Windows.
$ python -m venv venv
trong đó venv là thư mục chứa môi trường ảo.
Activate môi trường ảo:
$ venv\Scripts\activate
Khi không cần sử dụng nữa có thể deactivate môi trường ảo:
(venv) $ deactivate
Export các thư viện trong môi trường ảo:
(venv) $ pip freeze > requirements.txt
Sau khi dựng một môi trường ảo, nếu muốn cài đặt các thư viện từ file requirements.txt thì gõ:
(venv) $ pip install -r requirements.txt
Cài đặt thư viện:
$ pip install "fastapi[standard]"
Tạo file chính để chạy, giả sử main.py và thêm các nội dung sau:
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def root():
return {"message": "Hello World"}
Để chạy ứng dụng ở môi trường development, gõ lệnh:
$ fastapi dev main.py
Sau đó mở trình duyệt thực hiện test các địa chỉ sau:
http://localhost:8000 ==> sẽ trả về {"message": "Hello World"}
http://localhost:8000/docs ==> trả về trang Swagger liệt kê danh sách các API dùng để test
http://localhost:8000/redoc ==> hiện trang mô tả chi tiết cho từng API
Xây dựng các bộ API để thực hiện CRUD trên đối tượng sinh viên:
GET: /students ==> lấy thông tin tất cả sinh viên, có thể có tìm kiếm theo họ tên
GET: /students/{id} ==> lấy thông tin sinh viên theo {id}
POST: /students ==> thêm mới sinh viên
PUT: /students/{id} ==> cập nhật thông tin sinh viên
DELETE: /students/{id} ==> xóa sinh viên
Thông tin sinh viên lưu trữ ở file students.json dạng sau:
[
{"id": 1, "name": "Ly Tieu Long", "gpa": 6.9},
{"id": 2, "name": "Tra Hue Ny", "gpa": 9.6}
]
Tên model và các thư viện cần thiết như sau:
from pydantic import BaseModel
class Student(BaseModel):
id: int
name: str
gpa: float
Các thao tác này đều cần lấy thông tin sinh viên nên cần xây dựng một hàm để đọc danh sách sinh viên từ file students.json. Mã nguồn hàm này như sau:
DATA_FILE = "students.json"
def read_student_data():
try:
with open(DATA_FILE, encoding="utf8") as f:
return json.load(f)
except Exception as ex:
print(ex)
return []
Lấy thông tin tất cả sinh viên:
from typing import Optional
@app.get("/students")
def get_students(q: Optional[str] = None):
if q is None:
return read_student_data()
else:
return list(filter(lambda x: x["name"].find(q) > -1, read_student_data()))
Lấy thông tin một sinh viên:
@app.get("/students/{id}")
def get_student(id: int):
data = read_student_data()
for item in data:
if item["id"] == id:
print(item)
return {
"success": True, "data": item
}
return { "success": False, "message": f"Not found student {id}"}
@app.post("/students")
def insert_new_student(model: Student):
students = read_student_data()
for student in students:
if student["id"] == model.id:
print(f"Student id={id} existed")
return {
"success": False,
"message": f"Student id={id} existed"
}
students.append(
{
"id": model.id,
"name": model.name,
"gpa": model.gpa
}
)
with open(DATA_FILE, "w", encoding="utf8") as f:
json.dump(students, f)
return {"success": True, "data": model}
@app.put("/students/{id}")
def update_student(id: int):
pass
Sinh viên tự làm.
@app.delete("/students/{id}")
def delete_student(id: int):
pass
Sinh viên tự làm.
Docs: https://fastapi.tiangolo.com/reference/uploadfile
Giả sử các file upload lên sẽ lưu trữ trong thư mục data.
Các thư viện cần dùng:
from fastapi import FastAPI, UploadFile, File
import os
import shutil
from typing import List
DIRECTORY = os.getcwd()
Sau đây là 2 API dùng để upload một file và upload nhiều file.
@app.post("/images", tags=["UPLOAD"])
def upload_single_file(image: UploadFile = File(...)):
try:
file_save = os.path.join(DIRECTORY, "data", image.filename)
with open(file_save, "wb") as tmp:
shutil.copyfileobj(image.file, tmp)
return {"filename": image.filename}
except Exception as e:
print(e)
return {"success": False}
@app.post("/images/multiple", tags=["UPLOAD"])
def upload_multiple_file(images: List[UploadFile] = File(...)):
try:
uploaded_files = []
for image in images:
uploaded_files.append(image.filename)
file_save = os.path.join(DIRECTORY, "data", image.filename)
with open(file_save, "wb") as tmp:
shutil.copyfileobj(image.file, tmp)
return {"files": uploaded_files}
except Exception as e:
print(e)
return {"success": False}
from fastapi.responses import FileResponse
import os
@app.get("/download/{file_name}")
async def download_file(file_name: str):
file_path = f"./data/{file_name}"
if os.path.isfile(file_path):
print(f"Downloading file: {file_path}")
return FileResponse(
path=file_path,
filename=file_name,
headers={
"Content-Disposition": f"attachment; filename={file_name}"
}
)
else:
return {"error": "File not found"}