Pydantic The Ultimate Guide to Data Validation and Parsing in Python

Introduction to Pydantic

Pydantic is a Python library that provides data validation, data parsing, and settings management using Python type annotations. It is widely used by developers for its ease of use, reliability, and speed when it comes to enforcing data integrity in Python projects.

This guide aims to introduce you to Pydantic and walk you through dozens of its useful APIs, complete with practical code samples and a small application example to tie it all together.

Overview of Pydantic Features

  • Data validation with Python type hints
  • Automatic data parsing
  • Rich error handling and reporting
  • Environment variable parsing and settings management
  • Ease of integration with popular frameworks

Getting Started with Pydantic

Install Pydantic using pip:

  pip install pydantic

Basic Data Validation

You can define Pydantic models for validating and parsing data:

  from pydantic import BaseModel

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

  # Example usage
  user_data = {"id": 1, "name": "John Doe", "email": "john@example.com", "is_active": True}
  user = User(**user_data)
  print(user)

Nested Models

  from pydantic import BaseModel

  class Address(BaseModel):
      city: str
      state: str

  class User(BaseModel):
      id: int
      name: str
      address: Address

  user_data = {
      "id": 1,
      "name": "Jane Doe",
      "address": {"city": "New York", "state": "NY"}
  }
  user = User(**user_data)
  print(user)

Data Validation with Custom Logic

  from pydantic import BaseModel, validator

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

      @validator("email")
      def validate_email(cls, value):
          if "@" not in value:
              raise ValueError("Invalid email format")
          return value

  user_data = {"id": 2, "name": "Alice", "email": "alice@example.com"}
  user = User(**user_data)
  print(user)

Optional Fields and Default Values

  from pydantic import BaseModel
  from typing import Optional

  class Product(BaseModel):
      id: int
      name: str
      description: Optional[str] = None
      price: float = 9.99

  product_data = {"id": 101, "name": "Sample Product"}
  product = Product(**product_data)
  print(product)

Environment Variable Parsing with Pydantic Settings

Pydantic simplifies the management of app configurations and environment variables:

  from pydantic import BaseSettings

  class AppSettings(BaseSettings):
      app_name: str
      debug: bool = False
      version: str = "1.0.0"

      class Config:
          env_file = ".env"

  settings = AppSettings()
  print(settings)

Custom Error Messages

  from pydantic import BaseModel, Field

  class User(BaseModel):
      id: int = Field(..., title="ID", description="The user's ID")
      name: str = Field(..., min_length=2, max_length=50)

  user_data = {"id": 1, "name": "A"}
  try:
      user = User(**user_data)
  except Exception as e:
      print(e)

A Practical Application Example

Below is a basic Flask API implementation using Pydantic for data validation:

  from flask import Flask, request, jsonify
  from pydantic import BaseModel

  app = Flask(__name__)

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

  @app.route("/create_user", methods=["POST"])
  def create_user():
      try:
          user = User(**request.json)
          # Save user to the database (placeholder logic)
          return jsonify({"message": "User created", "user": user.dict()})
      except Exception as e:
          return jsonify({"error": str(e)}), 400

  if __name__ == "__main__":
      app.run(debug=True)

Conclusion

Pydantic is a versatile and powerful tool for Python developers, especially when working with data validation and settings. Its use of Python type annotations makes it seamless and Pythonic while providing robust features for managing your application’s data workflows.

Leave a Reply

Your email address will not be published. Required fields are marked *