cai dat fastapi

Cài Đặt FastAPI với MongoDB trên Ubuntu 24.04

FastAPI là một framework web hiện đại của Python được sử dụng để tạo các dịch vụ API với hiệu năng cao và hỗ trợ bất đồng bộ. Trong bài viết này, bạn sẽ được hướng dẫn cài đặt FastAPI cùng MongoDB trên hệ điều hành Ubuntu 24.04, từ việc cài đặt MongoDB, thiết lập môi trường Python ảo cho đến việc xây dựng API với các thao tác CRUD (Tạo – Đọc – Cập nhật – Xóa).

Mục lục

Yêu Cầu Hệ Thống

Trước khi bắt đầu, hãy đảm bảo bạn có:

  • Một hệ thống chạy Ubuntu 24.04.
  • Một tài khoản người dùng không phải root có quyền quản trị.
  • Kết nối Internet để cài đặt các gói cần thiết.

Cài Đặt MongoDB trên Ubuntu 24.04

Trong phần này, chúng ta sẽ cài đặt MongoDB – cơ sở dữ liệu NoSQL mạnh mẽ được sử dụng làm backend cho FastAPI.

Bước 1: Cập nhật gói và cài đặt tiện ích hỗ trợ

Mở terminal và chạy lệnh:

sudo apt update && sudo apt install gnupg curl -y

Bước 2: Thêm GPG key cho MongoDB

Chạy lệnh sau để thêm key:

curl -fsSL https://www.mongodb.org/static/pgp/server-8.0.asc | \
sudo gpg -o /usr/share/keyrings/mongodb-server-8.0.gpg --dearmor

Bước 3: Thêm repository MongoDB

Thêm repository bằng lệnh:

echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-8.0.gpg ] https://repo.mongodb.org/apt/ubuntu noble/mongodb-org/8.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-8.0.list

Bước 4: Cập nhật lại package index và cài đặt MongoDB

Chạy lệnh:

sudo apt update && sudo apt install mongodb-org

Nhấn Y khi được yêu cầu xác nhận.

Bước 5: Khởi động và kích hoạt MongoDB

Khởi động dịch vụ mongod và kích hoạt tự động khi khởi động hệ thống:

sudo systemctl enable --now mongod
sudo systemctl status mongod

Nếu MongoDB đang chạy, bạn có thể kiểm tra bằng cách kết nối vào shell của MongoDB:

mongosh

Để thoát, nhấn Ctrl+d.


Thiết Lập Python và Virtual Environment

Sau khi cài đặt MongoDB, chúng ta sẽ thiết lập môi trường Python để xây dựng dự án FastAPI.

Bước 1: Cài đặt Python, pip và venv

Chạy lệnh sau để cài đặt:

sudo apt install python3 python3-pip python3-venv -y

Bước 2: Chuyển sang người dùng thông thường

Nếu bạn đang sử dụng tài khoản root, hãy chuyển sang tài khoản người dùng không root:

su - username

Bước 3: Tạo thư mục dự án và thiết lập môi trường ảo

Tạo thư mục cho dự án và chuyển vào đó:

mkdir -p ~/app && cd ~/app

Tạo môi trường ảo và kích hoạt nó:

python3 -m venv .venv
source .venv/bin/activate

Lưu ý: Sau khi kích hoạt, dấu nhắc lệnh của bạn sẽ thay đổi hiển thị (venv). Để thoát môi trường ảo, chỉ cần gõ deactivate.


Tạo Dự Án FastAPI

Bây giờ, chúng ta sẽ cài đặt FastAPI và xây dựng cấu trúc dự án cơ bản.

Bước 1: Cài đặt FastAPI và Uvicorn

Trong môi trường ảo, chạy:

pip3 install fastapi uvicorn
  • FastAPI: Framework chính để xây dựng API.
  • Uvicorn: Server ASGI hỗ trợ bất đồng bộ cho FastAPI.

Bước 2: Tạo cấu trúc thư mục dự án

Tạo các thư mục và file cần thiết:

mkdir -p server/{models,routes}
touch main.py server/{app.py,database.py} server/models/itemModels.py server/routes/item.py

Cấu trúc dự án sẽ như sau:

~/app
 ├── main.py
 └── server
     ├── app.py
     ├── database.py
     ├── models
     │   └── itemModels.py
     └── routes
         └── item.py

Bước 3: Cấu hình file server/app.py

Mở file server/app.py và thêm đoạn mã sau:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def root():
    return {"message": "Hello FastAPI!"}
  • Nhập module FastAPI và khởi tạo đối tượng app.
  • Tạo endpoint root trả về thông báo “Hello FastAPI!”.

Bước 4: Cấu hình file main.py để chạy ứng dụng

Mở file main.py và thêm đoạn mã sau:

import uvicorn

if __name__ == "__main__":
    uvicorn.run("server.app:app", host="0.0.0.0", port=8080, reload=True)
  • Khi chạy file main.py, Uvicorn sẽ tải module FastAPI từ server/app.py.
  • Ứng dụng sẽ chạy trên địa chỉ 0.0.0.0 và cổng 8080.
  • Tùy chọn reload=True giúp tự động tải lại khi có thay đổi trong code.

Chạy Ứng Dụng FastAPI

Sau khi cấu hình xong, bạn có thể chạy ứng dụng bằng lệnh:

python3 main.py

Mở trình duyệt và truy cập vào địa chỉ http://SERVER_IP:8080/ (hoặc http://localhost:8080/) để xem thông báo “Hello FastAPI!”. Bạn cũng có thể dùng curl để kiểm tra.

Để truy cập tài liệu API do Swagger UI cung cấp, truy cập:

http://SERVER_IP:8080/docs

Kết Nối FastAPI với MongoDB

Để kết nối FastAPI với MongoDB, chúng ta sử dụng thư viện motor – driver MongoDB hỗ trợ asynchronous.

Bước 1: Cài đặt motor

Trong môi trường ảo, chạy:

pip3 install motor

Bước 2: Cấu hình kết nối trong file server/database.py

Mở file server/database.py và thêm mã sau:

from motor.motor_asyncio import AsyncIOMotorClient

MONGODB_HOST = "mongodb://localhost:27017"

# Kết nối đến MongoDB
connection = AsyncIOMotorClient(MONGODB_HOST)

# Kết nối đến database 'items'
database = connection.items

# Truy cập collection 'item_collection'
item_collection = database.get_collection("item_collection")
  • Import AsyncIOMotorClient từ motor.motor_asyncio.
  • Thiết lập biến MONGODB_HOST trỏ đến MongoDB trên cổng mặc định.
  • Kết nối đến database items và collection item_collection.

Tạo Model Dữ Liệu với Pydantic

Pydantic giúp định nghĩa schema và kiểm tra dữ liệu. Chúng ta sẽ tạo model cho dữ liệu item.

Bước 1: Cài đặt Pydantic

Chạy lệnh sau:

pip3 install pydantic

Bước 2: Cấu hình file server/models/itemModels.py

Mở file server/models/itemModels.py và thêm đoạn mã sau:

from pydantic import BaseModel, Field
from typing import Optional

class Item(BaseModel):
    name: str
    category: str
    stocks: int
    price: int = Field(gt=0)

    class Config:
        json_schema_extra = {
            "example": {
                "name": "Company Smart Watch",
                "category": "smartwatch",
                "stocks": 10,
                "price": 1000,
            }
        }

class ItemUpdate(BaseModel):
    name: Optional[str] = None
    category: Optional[str] = None
    stocks: Optional[int] = None
    price: Optional[int] = None

    class Config:
        json_schema_extra = {
            "example": {
                "name": "New Smart watch",
                "category": "new-smartwatch",
                "stocks": 5,
                "price": 500,
            }
        }
  • Model Item định nghĩa các trường bắt buộc: name, category, stocksprice (với điều kiện giá > 0).
  • Model ItemUpdate có các trường tùy chọn dùng cho việc cập nhật dữ liệu.

Thực Hiện Các Thao Tác CRUD

Chúng ta sẽ xây dựng các hàm thao tác CRUD trong file server/database.py để thực hiện các chức năng:

1. Hàm Trợ Giúp Chuyển Đổi Dữ Liệu

Thêm hàm item_helper để định dạng dữ liệu từ MongoDB:

from bson.objectid import ObjectId

def item_helper(item) -> dict:
    return {
        "id": str(item["_id"]),
        "name": item["name"],
        "category": item["category"],
        "stocks": item["stocks"],
        "price": item["price"],
    }

2. Thêm Item Mới

Thêm hàm add_item:

# Thêm một item mới
async def add_item(item_details: dict) -> dict:
    item = await item_collection.insert_one(item_details)
    new_item = await item_collection.find_one({"_id": item.inserted_id})
    return item_helper(new_item)

3. Lấy Tất Cả Item

Hàm get_items để truy xuất tất cả dữ liệu:

# Lấy tất cả các item
async def get_items():
    items = []
    async for item in item_collection.find():
        items.append(item_helper(item))
    return items

4. Lấy Item Cụ Thể theo ID

Hàm get_item để truy xuất item theo ID:

# Lấy chi tiết một item
async def get_item(id: str) -> dict:
    item = await item_collection.find_one({"_id": ObjectId(id)})
    if item:
        return item_helper(item)
    return "Item Not Found."

5. Cập Nhật Item

Hàm change_item cho việc cập nhật item:

# Cập nhật một item
async def change_item(id: str, data: dict):
    if len(data) < 1:
        return "Please input your data"
    find_item = await item_collection.find_one({"_id": ObjectId(id)})
    if find_item:
        item_update = await item_collection.update_one({"_id": ObjectId(id)}, {"$set": data})
        if item_update:
            return True
    return False

6. Xóa Item

Hàm delete_item cho việc xóa item:

# Xóa một item
async def delete_item(id: str):
    item = await item_collection.find_one({"_id": ObjectId(id)})
    if item:
        await item_collection.delete_one({"_id": ObjectId(id)})
        return f'Item {id} deleted.'
    return "Item Not Found."

Tạo Các Route cho CRUD Operations

Bây giờ, chúng ta sẽ tạo các route trong file server/routes/item.py để định nghĩa endpoint cho các thao tác CRUD.

Bước 1: Cấu Hình Route

Mở file server/routes/item.py và thêm đoạn mã sau:

from fastapi import APIRouter, Body
from fastapi.encoders import jsonable_encoder

from server.database import (
    add_item,
    get_items,
    get_item,
    change_item,
    delete_item,
)

from server.models.itemModels import (
    Item,
    ItemUpdate,
)

router = APIRouter()

Bước 2: Route Thêm Item Mới

# Thêm item mới qua POST
@router.post("/")
async def add_item_data(item: Item = Body(...)):
    item = jsonable_encoder(item)
    new_item = await add_item(item)
    return new_item

Bước 3: Route Lấy Tất Cả Item

# Lấy tất cả các item
@router.get("/")
async def get_item_data():
    items = await get_items()
    if items:
        return items
    return "No available item."

Bước 4: Route Lấy Chi Tiết Item theo ID

# Lấy chi tiết item qua ID
@router.get("/{id}")
async def get_item_details(id: str):
    item_details = await get_item(id)
    if item_details:
        return item_details
    return "Item not found."

Bước 5: Route Cập Nhật Item

# Cập nhật item
@router.put("/{id}")
async def update_item(id: str, data: ItemUpdate = Body(...)):
    data = {k: v for k, v in data.dict().items() if v is not None}
    updated_item = await change_item(id, data)
    if updated_item:
        return {f'Success: item {id} updated.'}
    return "Error"

Bước 6: Route Xóa Item

# Xóa item qua ID
@router.delete("/{id}")
async def remove_item(id: str):
    item_to_delete = await delete_item(id)
    if item_to_delete:
        return item_to_delete
    return {f'Item {id} Not Available.'}

Bước 7: Kết Nối Router với Ứng Dụng

Mở file server/app.py và thêm dòng sau để tích hợp router:

from server.routes.item import router as ItemRouter

app.include_router(ItemRouter, tags=["Item"], prefix="/item")

Như vậy, các endpoint CRUD sẽ được truy cập qua:

  • Thêm item mới: POST /item
  • Lấy tất cả item: GET /item
  • Lấy chi tiết item: GET /item/{id}
  • Cập nhật item: PUT /item/{id}
  • Xóa item: DELETE /item/{id}

Kiểm Tra API CRUD

Bước 1: Chạy Ứng Dụng

Trong terminal, đảm bảo bạn đang ở thư mục dự án với môi trường ảo được kích hoạt, sau đó chạy:

python3 main.py

Ứng dụng FastAPI sẽ chạy trên cổng 8080.

Bước 2: Kiểm Tra Qua Trình Duyệt

Mở trình duyệt và truy cập địa chỉ:

  • http://SERVER_IP:8080/ để xem thông báo “Hello FastAPI!”.
  • http://SERVER_IP:8080/docs để xem tài liệu API do Swagger UI cung cấp.

Tại giao diện Swagger, bạn có thể thực hiện các thao tác:

  • Thêm item mới: Sử dụng phương thức POST với endpoint /item.
  • Lấy tất cả item: Sử dụng GET tại /item.
  • Lấy chi tiết item: Sử dụng GET tại /item/{id}.
  • Cập nhật item: Sử dụng PUT tại /item/{id}.
  • Xóa item: Sử dụng DELETE tại /item/{id}.

Kết Luận

Chúc mừng bạn đã hoàn thành hướng dẫn cài đặt FastAPI với MongoDB trên Ubuntu 24.04. Trong bài viết này, bạn đã học được:

  • Cài đặt MongoDB và cấu hình repository trên Ubuntu 24.04.
  • Thiết lập môi trường Python với virtual environment.
  • Xây dựng dự án FastAPI với cấu trúc module rõ ràng.
  • Kết nối FastAPI với MongoDB sử dụng thư viện motor.
  • Xây dựng mô hình dữ liệu với Pydantic để kiểm tra và xác thực dữ liệu.
  • Thực hiện các thao tác CRUD (Tạo – Đọc – Cập nhật – Xóa) cho API.
  • Tạo các route cho CRUD operations và kiểm tra qua Swagger UI.

Với những kiến thức trên, bạn có thể dễ dàng mở rộng dự án, tích hợp thêm các tính năng bảo mật, xác thực và xử lý dữ liệu phức tạp cho các ứng dụng API hiện đại. Hãy tiếp tục khám phá và phát triển dự án của bạn với FastAPI và MongoDB!

Nếu bạn có thắc mắc hoặc góp ý, hãy để lại bình luận bên dưới và chia sẻ bài viết này đến cộng đồng. Chúc bạn thành công trong việc xây dựng các ứng dụng API hiệu năng cao!

Để lại một bình luận

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *