Traffine I/O

Bahasa Indonesia

2023-03-10

Pydantic untuk Validasi Data

Apa itu Pydantic

Pydantic adalah sebuah pustaka Python yang mempermudah proses validasi data dan pengelolaan pengaturan aplikasi. Pydantic menyediakan cara yang sederhana dan intuitif untuk mendefinisikan model data, memvalidasi data masukan, dan mengelola pengaturan aplikasi, semuanya dengan menjaga ketat pengetikan dan memberikan pesan kesalahan yang membantu.

Pydantic dirancang untuk bekerja dengan lancar dengan kerangka web populer seperti FastAPI dan Starlette, tetapi dapat digunakan dalam aplikasi Python apa pun yang memerlukan validasi data atau pengelolaan pengaturan.

Salah satu manfaat kunci dari Pydantic adalah kemampuannya untuk mengurangi kode boilerplate dan membuat validasi data lebih deklaratif. Pengembang dapat menentukan model data mereka menggunakan sintaks kelas yang sederhana, dan Pydantic akan menangani sisanya, termasuk pemeriksaan tipe, validasi, dan penanganan kesalahan.

Selain validasi data, Pydantic juga menawarkan sistem pengelolaan pengaturan yang kuat yang memungkinkan pengembang untuk dengan mudah memuat pengaturan aplikasi dari file konfigurasi, menggantinya dengan variabel lingkungan, dan menggunakannya dalam kode mereka.

Instalasi Pydantic

Untuk menginstal Pydantic, jalankan perintah berikut:

bash
$ pip install pydantic

Membuat Model Pydantic

Membuat model Pydantic adalah proses yang mudah dilakukan dengan mendefinisikan field dari model dan menambahkan validator yang diperlukan.

Berikut langkah-langkah untuk membuat model Pydantic:

  1. Impor kelas BaseModel dari modul pydantic:
python
from pydantic import BaseModel
  1. Tentukan model Anda dengan membuat subkelas BaseModel dan menambahkan field:
python
class User(BaseModel):
    id: int
    name: str
    email: str

Dalam contoh ini, kita telah mendefinisikan model User dengan tiga field: id, name, dan email. Perhatikan bahwa kita telah menentukan tipe setiap field menggunakan anotasi Python.

  1. Tambahkan validator ke field Anda jika diperlukan. Pydantic menyediakan berbagai validator bawaan, seperti MinValue, MaxValue, dan Regex, yang dapat digunakan untuk memastikan bahwa data masukan memenuhi persyaratan tertentu. Misalnya:
python
from pydantic import EmailStr

class User(BaseModel):
    id: int
    name: str
    email: EmailStr

Pada contoh yang diperbarui ini, kita telah mengganti field email dengan field EmailStr, yang secara otomatis memvalidasi bahwa data masukan adalah alamat email yang valid.

  1. Opsional, xtetapkan field mana yang dibutuhkan dan mana yang opsional menggunakan kelas Optional dan Required dari modul typing. Contohnya:
python
from typing import Optional

class User(BaseModel):
    id: int
    name: str
    email: Optional[EmailStr]

Pada contoh terakhir ini, kita menandai field email sebagai opsional dengan membungkusnya dalam kelas Optional. Ini berarti bahwa data masukan dapat valid meskipun field email tidak disertakan.

Dengan mengikuti langkah-langkah ini, Anda dapat dengan mudah membuat model Pydantic yang memvalidasi data masukan dan memastikan bahwa aplikasi Python Anda berjalan lancar.

Menggunakan Model Pydantic untuk Validasi Data

Pydantic memudahkan validasi data dalam aplikasi Python dengan menyediakan cara yang sederhana untuk mendefinisikan dan menggunakan model data. Dalam artikel ini, saya akan melihat bagaimana Anda dapat menggunakan model Pydantic untuk validasi data.

Memvalidasi Data Input

Untuk memvalidasi data input menggunakan Pydantic, Anda cukup perlu membuat model Pydantic yang mendefinisikan struktur yang diharapkan dari data input. Anda kemudian dapat menggunakan model ini untuk memvalidasi setiap data input yang diterima oleh aplikasi Anda.

Berikut adalah contoh cara memvalidasi data input menggunakan Pydantic:

python
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str

def create_user(user_data: dict):
    user = User(**user_data)
    # The above line validates the input data and raises a ValueError if it's invalid
    # If the input data is valid, you can continue with creating the user
    # ...

Pada contoh di atas, kita mendefinisikan model Pydantic User dengan tiga field: id, name, dan email. Kemudian kita mendefinisikan sebuah fungsi create_user yang menerima sebuah dictionary dari data input sebagai argumen.

Untuk memvalidasi data input, kita membuat sebuah instance baru dari model User menggunakan sintaks ** untuk membuka dictionary user_data. Jika data input valid, instance User berhasil dibuat. Jika data input tidak valid, sebuah ValueError akan ditimbulkan.

Memvalidasi Data Output

Selain memvalidasi data input, Pydantic juga dapat digunakan untuk memvalidasi data output. Hal ini berguna ketika Anda ingin memastikan bahwa data yang dikembalikan oleh aplikasi Anda memenuhi persyaratan tertentu.

Berikut adalah contoh cara memvalidasi data output menggunakan Pydantic:

python
from typing import List
from pydantic import BaseModel

class User(BaseModel):
    id: int
    name: str
    email: str

def get_users() -> List[User]:
    # Get a list of users from the database
    users_data = [
        {"id": 1, "name": "Alice", "email": "alice@example.com"},
        {"id": 2, "name": "Bob", "email": "bob@example.com"}
    ]
    # Convert the list of user data dictionaries to a list of User instances
    users = [User(**user_data) for user_data in users_data]
    # Validate the output data
    return users

Pada contoh ini, kita mendefinisikan sebuah fungsi get_users yang mengembalikan sebuah daftar data pengguna. Kita mengubah daftar ini dari kamus data menjadi daftar instance User menggunakan list comprehension.

Untuk memvalidasi data output, kita cukup mengembalikan daftar instance User. Pydantic akan secara otomatis memvalidasi setiap instance User dan menimbulkan pengecualian jika ada salah satu dari mereka tidak valid.

Validator Bawaan

Pydantic dilengkapi dengan sejumlah validator bawaan yang dapat Anda gunakan untuk memastikan bahwa model data Anda memenuhi persyaratan tertentu. Dalam artikel ini, saya akan menjelaskan beberapa validator yang paling umum digunakan dan memberikan contoh cara menggunakannya.

EmailStr

Validator ini memastikan bahwa sebuah string adalah alamat email yang valid.

python
from pydantic import BaseModel, EmailStr

class User(BaseModel):
    name: str
    email: EmailStr

UrlStr

Validator ini memastikan bahwa sebuah string adalah URL yang valid.

python
from pydantic import BaseModel, UrlStr

class Website(BaseModel):
    name: str
    url: UrlStr

Length

Validator ini memastikan bahwa sebuah string memiliki panjang minimum dan/atau maksimum.

python
from pydantic import BaseModel, constr, Length

class User(BaseModel):
    name: constr(min_length=1, max_length=50)
    bio: constr(max_length=500)

MinMaxValue

Validator ini memastikan bahwa sebuah nilai numerik lebih besar dari atau sama dengan nilai minimum atau kurang dari atau sama dengan nilai maksimum, secara berturut-turut.

python
from pydantic import BaseModel, conint, MinValue, MaxValue

class Product(BaseModel):
    name: str
    price: conint(gt=0, le=10000)
    quantity: conint(ge=0)
    discount: conint(ge=0, le=50)

Regex

Validator ini memastikan bahwa sebuah string cocok dengan pola ekspresi reguler.

python
from pydantic import BaseModel, constr, Regex

class User(BaseModel):
    name: constr(regex=r'^[a-zA-Z ]+$')

ConstrainedStr

Validator ini memastikan bahwa sebuah string memenuhi serangkaian batasan yang ditentukan oleh kelas induknya.

python
from pydantic import BaseModel, ConstrainedStr

class Password(ConstrainedStr):
    min_length = 8
    max_length = 50
    regex = r'[a-zA-Z0-9_-]+'

class User(BaseModel):
    email: EmailStr
    password: Password

ConstrainedInt

Validator ini memastikan bahwa sebuah bilangan bulat memenuhi serangkaian batasan yang ditentukan oleh kelas induknya.

python
from pydantic import BaseModel, ConstrainedInt

class Age(ConstrainedInt):
    ge = 0
    le = 120

class User(BaseModel):
    name: str
    age: Age

Decimal

Validator ini memastikan bahwa sebuah nilai numerik adalah desimal dengan jumlah digit desimal tertentu.

python
from pydantic import BaseModel, condecimal

class Product(BaseModel):
    price: condecimal(ge=0, le=10000, max_digits=8, decimal_places=2)

Uuid

Validator ini memastikan bahwa sebuah nilai string adalah UUID yang valid.

python
from pydantic import BaseModel, UUID4

class Order(BaseModel):
    id: UUID4

IPv4Address

Validator ini memastikan bahwa sebuah nilai string adalah alamat IPv4 yang valid.

python
from pydantic import BaseModel, IPv4Address

class NetworkInterface(BaseModel):
    ip_address: IPv4Address

DirectoryPath

Validator ini memastikan bahwa sebuah nilai string adalah jalur direktori yang valid.

python
from pydantic import BaseModel, DirectoryPath

class Config(BaseModel):
    data_dir: DirectoryPath

FilePath

Validator ini memastikan bahwa sebuah nilai string adalah jalur file yang valid.

python
from pydantic import BaseModel, FilePath

class Config(BaseModel):
    data_file: FilePath

Fitur Lanjutan Pydantic

Pydantic menyediakan beberapa fitur lanjutan untuk membuat model data yang kuat dan fleksibel. Berikut adalah beberapa fitur utama:

Membuat Validasi Kustom

Pydantic memungkinkan Anda untuk membuat validasi kustom untuk bidang, memberi Anda kontrol yang sangat baik atas bagaimana data Anda divalidasi. Anda dapat menentukan fungsi validator sendiri dan kemudian menggunakannya dalam model data Anda.

python
from pydantic import BaseModel, validator

class User(BaseModel):
    name: str
    age: int

    @validator('age')
    def validate_age(cls, age):
        if age < 0 or age > 120:
            raise ValueError('Invalid age')
        return age

Dalam contoh ini, kita menentukan validator kustom untuk bidang age pada model User yang memeriksa apakah usia berada antara 0 dan 120.

Validasi Dua Bidang

Satu penggunaan umum untuk validator kustom adalah memvalidasi dua bidang sekaligus, memastikan bahwa nilai dari dua bidang memenuhi kriteria atau batasan tertentu.

Misalnya, katakanlah Anda memiliki model Pydantic yang mewakili pesanan pengiriman, dengan dua kolom yang mewakili alamat pengiriman: street_address dan zip_code. Anda ingin memastikan bahwa zip_code sesuai dengan street_address yang benar, berdasarkan pemetaan kode pos ke alamat jalan.

Untuk mencapai ini, Anda dapat menentukan validator kustom untuk kedua kolom street_address dan zip_code yang memeriksa apakah kombinasi nilai adalah valid:

python
from pydantic import BaseModel, validator

class ShippingOrder(BaseModel):
    street_address: str
    zip_code: str

    @validator('zip_code')
    def validate_zip_code(cls, value, values):
        # get the value of the street_address column from the values dictionary
        street_address = values.get('street_address')

        # perform validation logic
        if not is_valid_zip_code(street_address, value):
            raise ValueError('Invalid zip code for street address')

        return value

    @validator('street_address')
    def validate_street_address(cls, value, values):
        # get the value of the zip_code column from the values dictionary
        zip_code = values.get('zip_code')

        # perform validation logic
        if not is_valid_zip_code(value, zip_code):
            raise ValueError('Invalid street address for zip code')

        return value

def is_valid_zip_code(street_address, zip_code):
    # perform validation logic, e.g. using a mapping of zip codes to street addresses
    if zip_code == '12345' and street_address != '123 Main St.':
        return False

    return True

Pada contoh ini, kita menentukan dua validator kustom, satu untuk kolom zip_code dan satu lagi untuk kolom street_address. Setiap validator mengambil dua argumen: nama field yang divalidasi (zip_code atau street_address) dan nilainya (value), serta kamus nilai untuk semua field dalam model (values).

Masing-masing validator juga memanggil fungsi is_valid_zip_code terpisah untuk melakukan logika validasi sebenarnya. Dalam contoh ini, fungsi is_valid_zip_code memeriksa apakah kombinasi street_address dan zip_code valid, berdasarkan pemetaan kode pos ke alamat jalan. Jika kombinasinya tidak valid, validator akan menimbulkan kesalahan ValueError dengan pesan kesalahan.

Bekerja dengan Enum

Pydantic menyediakan dukungan bawaan untuk enumerasi, memungkinkan Anda untuk mendefinisikan field yang hanya dapat mengambil nilai tertentu. Ini membantu memastikan bahwa model data Anda akurat dan aman.

python
from enum import Enum
from pydantic import BaseModel

class Gender(Enum):
    MALE = 'male'
    FEMALE = 'female'

class User(BaseModel):
    name: str
    gender: Gender

Pada contoh ini, kita mendefinisikan sebuah Enum untuk Gender dan menggunakannya dalam model User untuk memastikan bahwa kolom gender hanya dapat memiliki nilai male atau female.

Menangani Model Bersarang

Pydantic memungkinkan Anda untuk mendefinisikan model bersarang, yang dapat digunakan untuk merepresentasikan struktur data yang kompleks.

python
from pydantic import BaseModel

class Location(BaseModel):
    latitude: float
    longitude: float

class User(BaseModel):
    name: str
    location: Location

Pada contoh ini, kita mendefinisikan model Location dan menggunakannya sebagai kolom di dalam model User untuk merepresentasikan lokasi pengguna.

Menggunakan Pydantic dengan Pustaka ORM

Pydantic dapat digunakan dengan pustaka ORM populer seperti SQLAlchemy dan Tortoise-ORM, sehingga memudahkan Anda untuk mengonversi antara model database dan model Pydantic.

python
from sqlalchemy import Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base
from pydantic import BaseModel

Base = declarative_base()

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    age = Column(Integer)

class UserIn(BaseModel):
    name: str
    age: int

class UserOut(UserIn):
    id: int

    class Config:
        orm_mode = True

Pada contoh ini, kita mendefinisikan model SQLAlchemy untuk User dan kemudian mendefinisikan model Pydantic untuk masukan dan keluaran. Kelas Config dengan orm_mode=True memberi tahu Pydantic untuk mengonversi model SQLAlchemy ke model Pydantic dan sebaliknya.

Referensi

https://docs.pydantic.dev/

Ryusei Kakujo

researchgatelinkedingithub

Focusing on data science for mobility

Bench Press 100kg!