DRF Pydantic Integration
drf-pydantic is a Python library that enables seamless integration of Pydantic models with the Django REST Framework (DRF). It allows developers to use Pydantic for data validation and serialization within DRF serializers, leveraging Pydantic's robust schema definition and validation capabilities. The current version is 2.9.1, and it typically follows a release cadence tied to Django, DRF, or Pydantic updates, with minor releases for features and bug fixes.
Common errors
-
TypeError: 'PydanticModelSerializer' object has no attribute 'get_serializer_class'
cause Attempting to use `PydanticModelSerializer` without defining the `Meta.model` attribute, or providing an invalid model type.fixEnsure your `PydanticModelSerializer` class has an inner `Meta` class with `model = YourPydanticModel` pointing to a valid Pydantic model that originated from a Django model. -
ValidationError: 1 validation error for ItemCreate\nname\n field required (type=value_error.missing)
cause Pydantic validation failed because incoming data does not match the schema defined in the Pydantic model (e.g., a required field is missing or has the wrong type).fixInspect the error message for the specific field and validation rule that failed. Adjust the incoming request data to conform to the Pydantic model's requirements. Ensure your Pydantic model is correctly defined. -
django.core.exceptions.ImproperlyConfigured: 'PydanticModelSerializer' requires a 'model' attribute to be specified in the 'Meta' class or as a keyword argument.
cause This error occurs with `PydanticModelSerializer` if it cannot correctly infer or is not explicitly told which Pydantic model to use, usually when the Pydantic model is not properly derived from a Django model or the `Meta.model` is missing/incorrect.fixFor `PydanticModelSerializer`, ensure `class Meta: model = YourPydanticModel` is set correctly, and that `YourPydanticModel` is indeed a Pydantic model generated from a Django model (e.g., using `django-pydantic`). If using a plain Pydantic model, switch to `PydanticSerializer`.
Warnings
- breaking Version 2.x was a complete rewrite, introducing `PydanticSerializer` and `PydanticModelSerializer` as the primary components. Code written for 1.x (which used `PydanticField` and `PydanticMixin`) is not compatible with 2.x.
- gotcha There are two main serializers: `PydanticSerializer` for general Pydantic `BaseModel`s, and `PydanticModelSerializer` for Pydantic models specifically generated from Django models (often using `django-pydantic`). Using `PydanticModelSerializer` with a regular `BaseModel` not derived from a Django model will lead to errors.
- gotcha When using `PydanticSerializer` or `PydanticModelSerializer`, you must explicitly define `class Meta: model = YourPydanticModel` within your serializer. Forgetting this or misconfiguring it will prevent the serializer from functioning correctly.
Install
-
pip install drf-pydantic
Imports
- PydanticSerializer
from drf_pydantic.serializers import PydanticSerializer
- PydanticModelSerializer
from drf_pydantic.serializers import PydanticModelSerializer
- apply_patch
from drf_pydantic.patch import apply_patch
Quickstart
from pydantic import BaseModel, Field
from typing import Optional
from drf_pydantic.serializers import PydanticSerializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
# 1. Define your Pydantic model
class ItemCreate(BaseModel):
name: str = Field(..., max_length=100)
description: Optional[str] = None
price: float = Field(..., gt=0)
# 2. Create a PydanticSerializer
class ItemCreateSerializer(PydanticSerializer):
class Meta:
model = ItemCreate
# 3. Use the serializer in a DRF View
class ItemAPIView(APIView):
def post(self, request):
serializer = ItemCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
# Access validated data as a Pydantic model instance
item_instance: ItemCreate = serializer.validated_data
# In a real application, you would save `item_instance` to a database
# or perform other business logic here.
print(f"Received item: {item_instance.dict()}")
return Response(item_instance.dict(), status=status.HTTP_201_CREATED)
def get(self, request):
# Example of serializing a Pydantic instance for output
example_item = ItemCreate(name="Sample Widget", price=29.99)
serializer = ItemCreateSerializer(instance=example_item)
return Response(serializer.data)