0

30 Ngày Chinh Phục FastAPI - [Ngày 3]

Ngày 3: Pydantic và Validate Dữ liệu

1. Giới thiệu về Pydantic

1.1. Là gì?

Pydantic là một thư viện Python giúp chúng ta quản lý và kiểm tra dữ liệu một cách dễ dàng và hiệu quả. Hãy tưởng tượng Pydantic như một người bạn rất thông minh, giúp chúng ta kiểm tra xem các món đồ chơi (dữ liệu) có đúng như chúng ta muốn hay không.

  • Nó là một cách để nói với máy tính rằng "mình muốn dữ liệu phải như thế này nè!"
  • Ví dụ, mình muốn tên của một món đồ chơi phải là chữ, giá của nó phải là số.
  • Nếu ai đó đưa cho mình một món đồ chơi mà tên lại là số, hoặc giá lại là chữ, Pydantic sẽ nói "Không được đâu! Cái này không đúng!"
  • Nhờ Pydantic, code của mình sẽ dễ đọc hơn, giống như một cuốn truyện tranh có hình ảnh minh họa vậy đó!

Túm lại:

  • Kiểu dữ liệu: Pydantic sử dụng "type hints" (gợi ý kiểu) của Python để nói với máy tính rằng "tôi muốn dữ liệu phải như thế này".
  • Kiểm tra dữ liệu: Nếu ai đó đưa cho chúng ta một món đồ chơi không đúng kiểu, Pydantic sẽ thông báo lỗi ngay lập tức.
  • Rõ ràng và dễ đọc: Nhờ Pydantic, code của chúng ta sẽ giống như một cuốn sách dễ hiểu, không bị rối mắt.

1.2. Tại sao cần?

Pydantic giúp chúng ta đảm bảo rằng mọi thứ đều hoạt động trơn tru. Đây là những lý do chính:

  • Đảm bảo tính chính xác: Dữ liệu luôn ở định dạng mà chúng ta mong muốn.
  • Ngăn ngừa lỗi: Giúp tránh những lỗi gây ra bởi dữ liệu không hợp lệ.
  • Tài liệu API chính xác: Tạo ra tài liệu cho API rõ ràng và dễ hiểu hơn.
  • Cải thiện trải nghiệm người dùng: Người dùng sẽ có trải nghiệm tốt hơn khi mọi thứ hoạt động đúng.

2. Thực chiến

2.1. Cách để định nghĩa Model Pydantic:

Cài thư viện Pydantic bằng lệnh:

pip install pydantic

Để tạo ra một Pydantic Model, mình sẽ tạo ra một "khuôn mẫu" để tạo ra các đối tượng dữ liệu.

  • Đầu tiên, mình tạo một "ngôi nhà" (class) đặc biệt bằng cách kế thừa từ pydantic.BaseModel.
  • Sau đó, mình "trang trí" ngôi nhà bằng các thuộc tính, ví dụ như name, description, price, tax.
  • Mình cũng cần nói cho Pydantic biết mỗi thuộc tính là loại gì, ví dụ name là chữ (string), price là số (float).
  • Nếu một thuộc tính nào đó có thể không có (ví dụ, không phải món đồ chơi nào cũng có "description"), mình có thể dùng typing.Optional hoặc | None để nói với Pydantic rằng "thuộc tính này có thể không có".
  • Mình cũng có thể đặt giá trị mặc định cho các thuộc tính, ví dụ nếu không ai nói gì về tax, mình sẽ mặc định nó là 0.
# Định nghĩa một Pydantic Model
from typing import Optional
from pydantic import BaseModel

class Item(BaseModel):
    name: str
    description: Optional[str] = None #Hoặc description: str | None = None (từ Python 3.10)
    price: float
    tax: Optional[float] = None #Hoặc tax: float | None = None (từ Python 3.10)
  • name: str: Thuộc tính name phải là một chuỗi (text).
  • description: str | None = None: Thuộc tính description có thể là một chuỗi (text) hoặc không có gì (None). Nếu không ai nói gì, nó sẽ là None.
  • price: float: Thuộc tính price phải là một số (ví dụ: 10.5, 20.0).
  • tax: float | None = None: Thuộc tính tax có thể là một số hoặc không có gì. Nếu không ai nói gì, nó sẽ là None.

Mình có thể tạo ra những "ngôi nhà" phức tạp hơn bằng cách lồng các Pydantic Model vào nhau. Giống như mình xây một tòa lâu đài bằng LEGO, mình cần nhiều viên gạch LEGO khác nhau vậy đó! Đôi khi, người ta còn gọi Pydantic Model là "model" hoặc "schema".

2.2. Bài tập thực hành

Bài tập 1: Tạo Model cho Người dùng

=> Hãy tạo một Pydantic Model cho người dùng (User) với các thuộc tính sau:

  • username: chuỗi (string)
  • email: chuỗi (string)
  • full_name: chuỗi (string) có thể là None
  • age: số nguyên (integer) có thể là None
# Định nghĩa User Model
from pydantic import BaseModel
from typing import Optional

class User(BaseModel):
    username: str
    email: str
    full_name: Optional[str] = None
    age: Optional[int] = None

Bài tập 2: Kiểm tra dữ liệu

Hãy viết một hàm để kiểm tra xem một đối tượng User có hợp lệ hay không. Sử dụng model mà con vừa tạo ở bài tập 1.

def create_user(user_data):
    try:
        user = User(**user_data)
        print("User created successfully:", user)
    except Exception as e:
        print("Error:", e)

# Thử nghiệm với dữ liệu hợp lệ
create_user({
    "username": "john_doe",
    "email": "john@example.com",
    "full_name": "John Doe",
    "age": 30
})

# Thử nghiệm với dữ liệu không hợp lệ
create_user({
    "username": "jane_doe",
    "email": "jane@example.com",
    "full_name": "Jane Doe",
    "age": "thirty"  # Đây là lỗi, age phải là số nguyên
})

2.3. Bài tập nâng cao

Bài tập 3: Lồng nhiều Models vào nhau

Hãy tạo một model cho địa chỉ (Address) và lồng nó vào model User. Địa chỉ sẽ có các thuộc tính sau:

  • street: chuỗi (string)
  • city: chuỗi (string)
  • state: chuỗi (string)
  • zip_code: chuỗi (string)
class Address(BaseModel):
    street: str
    city: str
    state: str
    zip_code: str

class UserWithAddress(BaseModel):
    username: str
    email: str
    full_name: Optional[str] = None
    age: Optional[int] = None
    address: Address

# Thử nghiệm với UserWithAddress Model
create_user_with_address({
    "username": "john_doe",
    "email": "john@example.com",
    "full_name": "John Doe",
    "age": 30,
    "address": {
        "street": "123 Main St",
        "city": "Anytown",
        "state": "CA",
        "zip_code": "12345"
    }
})

2.4. Kết

Pydantic giúp chúng ta định nghĩa cấu trúc dữ liệu rõ ràng và kiểm tra tính hợp lệ của dữ liệu trước khi sử dụng. Học được cách định nghĩa model, kiểm tra dữ liệu và lồng nhiều model vào nhau. Bài tiếp theo sẽ là - Ngày 4: Swagger UI, Query Parameters, Path Parameters


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí