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:
$ 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:
- Impor kelas
BaseModel
dari modul pydantic:
from pydantic import BaseModel
- Tentukan model Anda dengan membuat subkelas
BaseModel
dan menambahkan field:
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.
- Tambahkan validator ke field Anda jika diperlukan. Pydantic menyediakan berbagai validator bawaan, seperti
MinValue
,MaxValue
, danRegex
, yang dapat digunakan untuk memastikan bahwa data masukan memenuhi persyaratan tertentu. Misalnya:
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.
- Opsional, xtetapkan field mana yang dibutuhkan dan mana yang opsional menggunakan kelas
Optional
danRequired
dari modultyping
. Contohnya:
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:
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:
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.
from pydantic import BaseModel, EmailStr
class User(BaseModel):
name: str
email: EmailStr
UrlStr
Validator ini memastikan bahwa sebuah string adalah URL yang valid.
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.
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.
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.
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.
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.
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.
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.
from pydantic import BaseModel, UUID4
class Order(BaseModel):
id: UUID4
IPv4Address
Validator ini memastikan bahwa sebuah nilai string adalah alamat IPv4 yang valid.
from pydantic import BaseModel, IPv4Address
class NetworkInterface(BaseModel):
ip_address: IPv4Address
DirectoryPath
Validator ini memastikan bahwa sebuah nilai string adalah jalur direktori yang valid.
from pydantic import BaseModel, DirectoryPath
class Config(BaseModel):
data_dir: DirectoryPath
FilePath
Validator ini memastikan bahwa sebuah nilai string adalah jalur file yang valid.
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.
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:
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.
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.
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.
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