Web APIs for Django, made easy.
—
Comprehensive field types for data validation and serialization in Django REST Framework. Includes basic types, specialized fields, relationship fields, and custom validation support.
Foundation class for all serializer fields providing core validation and transformation functionality.
class Field:
"""
Base class for all serializer fields.
"""
def __init__(self, read_only=False, write_only=False, required=None, default=empty,
initial=empty, source=None, label=None, help_text=None,
style=None, error_messages=None, validators=None, allow_null=False):
"""
Initialize field with configuration options.
Args:
read_only (bool): Field is read-only
write_only (bool): Field is write-only
required (bool): Field is required for input
default: Default value if not provided
initial: Initial value for forms
source (str): Source attribute name
label (str): Human readable label
help_text (str): Help text for field
style (dict): Style hints for rendering
error_messages (dict): Custom error messages
validators (list): List of validator functions
allow_null (bool): Allow None values
"""
def bind(self, field_name, parent):
"""
Bind field to its parent serializer.
Args:
field_name (str): Field name in serializer
parent: Parent serializer instance
"""
def get_value(self, dictionary):
"""
Extract field value from input dictionary.
Args:
dictionary (dict): Input data dictionary
Returns:
Field value or empty sentinel
"""
def get_attribute(self, instance):
"""
Extract field value from object instance.
Args:
instance: Object instance to serialize
Returns:
Attribute value
"""
def to_representation(self, value):
"""
Transform internal value to serialized representation.
Args:
value: Internal Python value
Returns:
Serialized representation
"""
def to_internal_value(self, data):
"""
Transform input data to internal Python value.
Args:
data: Input data to validate
Returns:
Validated internal value
Raises:
ValidationError: If validation fails
"""
def validate(self, value):
"""
Validate internal value against field validators.
Args:
value: Value to validate
Returns:
Validated value
Raises:
ValidationError: If validation fails
"""Core field types for common data validation needs.
class BooleanField(Field):
"""Boolean field accepting True/False values."""
def __init__(self, **kwargs): ...
class CharField(Field):
"""
String field with length validation.
Args:
max_length (int): Maximum string length
min_length (int): Minimum string length
allow_blank (bool): Allow empty strings
trim_whitespace (bool): Strip leading/trailing whitespace
"""
def __init__(self, max_length=None, min_length=None, allow_blank=False,
trim_whitespace=True, **kwargs): ...
class EmailField(CharField):
"""Email address validation field."""
def __init__(self, **kwargs): ...
class RegexField(CharField):
"""
String field validated against regex pattern.
Args:
regex (str or Pattern): Regular expression pattern
"""
def __init__(self, regex, **kwargs): ...
class SlugField(CharField):
"""Slug validation field (letters, numbers, underscores, hyphens)."""
def __init__(self, **kwargs): ...
class URLField(CharField):
"""URL validation field."""
def __init__(self, **kwargs): ...
class UUIDField(Field):
"""
UUID field supporting string and UUID object formats.
Args:
format (str): Output format ('hex_verbose', 'hex', 'int', 'urn')
"""
def __init__(self, format='hex_verbose', **kwargs): ...
class IPAddressField(CharField):
"""
IP address validation field supporting IPv4 and IPv6.
Args:
protocol (str): 'both', 'ipv4', or 'ipv6'
unpack_ipv4 (bool): Unpack IPv4-mapped IPv6 addresses
"""
def __init__(self, protocol='both', unpack_ipv4=False, **kwargs): ...Fields for numeric data with range validation.
class IntegerField(Field):
"""
Integer field with range validation.
Args:
max_value (int): Maximum allowed value
min_value (int): Minimum allowed value
"""
def __init__(self, max_value=None, min_value=None, **kwargs): ...
class FloatField(Field):
"""
Float field with range validation.
Args:
max_value (float): Maximum allowed value
min_value (float): Minimum allowed value
"""
def __init__(self, max_value=None, min_value=None, **kwargs): ...
class DecimalField(Field):
"""
Precise decimal field for financial calculations.
Args:
max_digits (int): Maximum number of digits
decimal_places (int): Number of decimal places
coerce_to_string (bool): Return as string instead of Decimal
max_value (Decimal): Maximum allowed value
min_value (Decimal): Minimum allowed value
"""
def __init__(self, max_digits, decimal_places, coerce_to_string=None,
max_value=None, min_value=None, **kwargs): ...Fields for temporal data with format support.
class DateTimeField(Field):
"""
DateTime field with format parsing and output.
Args:
format (str): Output format string or 'iso-8601'
input_formats (list): List of acceptable input formats
default_timezone (timezone): Default timezone for naive datetimes
"""
def __init__(self, format=empty, input_formats=None, default_timezone=None, **kwargs): ...
class DateField(Field):
"""
Date field with format parsing and output.
Args:
format (str): Output format string or 'iso-8601'
input_formats (list): List of acceptable input formats
"""
def __init__(self, format=empty, input_formats=None, **kwargs): ...
class TimeField(Field):
"""
Time field with format parsing and output.
Args:
format (str): Output format string or 'iso-8601'
input_formats (list): List of acceptable input formats
"""
def __init__(self, format=empty, input_formats=None, **kwargs): ...
class DurationField(Field):
"""
Duration field supporting various input formats.
Args:
max_value (timedelta): Maximum duration
min_value (timedelta): Minimum duration
"""
def __init__(self, max_value=None, min_value=None, **kwargs): ...Fields for constrained choices and file handling.
class ChoiceField(Field):
"""
Field that validates against a set of choices.
Args:
choices (list): List of valid choices as (value, label) tuples
allow_blank (bool): Allow empty string choice
"""
def __init__(self, choices, allow_blank=False, **kwargs): ...
class MultipleChoiceField(ChoiceField):
"""
Field that validates multiple selections from choices.
Args:
choices (list): List of valid choices
allow_empty (bool): Allow empty list
"""
def __init__(self, allow_empty=True, **kwargs): ...
class FileField(Field):
"""
File upload field.
Args:
max_length (int): Maximum filename length
allow_empty_file (bool): Allow empty files
use_url (bool): Use URL instead of filename in representation
"""
def __init__(self, max_length=None, allow_empty_file=False, use_url=True, **kwargs): ...
class ImageField(FileField):
"""
Image file field with validation.
"""
def __init__(self, **kwargs): ...Fields for complex data structures.
class ListField(Field):
"""
Field for lists of items with child validation.
Args:
child (Field): Field for validating list items
allow_empty (bool): Allow empty lists
max_length (int): Maximum list length
min_length (int): Minimum list length
"""
def __init__(self, child=None, allow_empty=True, max_length=None, min_length=None, **kwargs): ...
class DictField(Field):
"""
Field for dictionaries with optional child validation.
Args:
child (Field): Field for validating dictionary values
allow_empty (bool): Allow empty dictionaries
"""
def __init__(self, child=None, allow_empty=True, **kwargs): ...
class HStoreField(DictField):
"""PostgreSQL HStore field (string keys and values only)."""
def __init__(self, **kwargs): ...
class JSONField(Field):
"""
Field for JSON data with optional binary encoding.
Args:
binary (bool): Store as binary JSON (PostgreSQL)
encoder (JSONEncoder): Custom JSON encoder class
"""
def __init__(self, binary=False, encoder=None, **kwargs): ...Specialized fields for specific use cases.
class ReadOnlyField(Field):
"""
Read-only field that returns attribute value without validation.
"""
def __init__(self, **kwargs):
kwargs['read_only'] = True
super().__init__(**kwargs)
class HiddenField(Field):
"""
Hidden field with default value, not included in input validation.
"""
def __init__(self, **kwargs):
kwargs['write_only'] = True
super().__init__(**kwargs)
class SerializerMethodField(Field):
"""
Field that gets its value by calling a method on the serializer.
Args:
method_name (str): Name of serializer method to call
"""
def __init__(self, method_name=None, **kwargs):
kwargs['read_only'] = True
self.method_name = method_name
super().__init__(**kwargs)
class ModelField(Field):
"""
Field that wraps a Django model field for validation.
Args:
model_field: Django model field instance
"""
def __init__(self, model_field, **kwargs): ...Support for custom validation logic.
# Special values and exceptions
empty = object() # Sentinel for no data provided
class SkipField(Exception):
"""Exception to skip field during serialization."""
# Default value classes
class CreateOnlyDefault:
"""Default value only used during object creation."""
def __init__(self, default): ...
def __call__(self): ...
class CurrentUserDefault:
"""Default to current user from request context."""
def __call__(self): ...
# Utility functions
def is_simple_callable(obj):
"""
Check if object is a simple callable (no required arguments).
Args:
obj: Object to check
Returns:
bool: True if simple callable
"""
def get_attribute(instance, attrs):
"""
Get nested attribute value using dot notation.
Args:
instance: Object instance
attrs (list): List of attribute names
Returns:
Attribute value
"""
def to_choices_dict(choices):
"""
Convert choices list to dictionary format.
Args:
choices: Choices in various formats
Returns:
dict: Normalized choices dictionary
"""Built-in validator classes for complex validation scenarios, particularly useful for model-level constraints and uniqueness checks.
class UniqueValidator:
"""
Validator that ensures field value is unique within a queryset.
Corresponds to unique=True on model fields.
"""
message = 'This field must be unique.'
requires_context = True
def __init__(self, queryset, message=None, lookup='exact'):
"""
Args:
queryset: QuerySet to check uniqueness against
message (str): Custom error message
lookup (str): Field lookup type for filtering
"""
def __call__(self, value, serializer_field):
"""Validate value uniqueness."""
class UniqueTogetherValidator:
"""
Validator that ensures field combinations are unique.
Corresponds to unique_together model Meta option.
"""
message = 'The fields {field_names} must make a unique set.'
missing_message = 'This field is required.'
requires_context = True
def __init__(self, queryset, fields, message=None):
"""
Args:
queryset: QuerySet to check uniqueness against
fields (list): List of field names that must be unique together
message (str): Custom error message
"""
class UniqueForDateValidator:
"""
Validator that ensures field is unique for a given date.
Corresponds to unique_for_date model field option.
"""
message = 'This field must be unique for the "{date_field}" date.'
requires_context = True
def __init__(self, queryset, field, date_field, message=None):
"""
Args:
queryset: QuerySet to check uniqueness against
field (str): Field name to validate
date_field (str): Date field to check uniqueness within
message (str): Custom error message
"""
class UniqueForMonthValidator:
"""
Validator that ensures field is unique for a given month.
Corresponds to unique_for_month model field option.
"""
message = 'This field must be unique for the "{date_field}" month.'
class UniqueForYearValidator:
"""
Validator that ensures field is unique for a given year.
Corresponds to unique_for_year model field option.
"""
message = 'This field must be unique for the "{date_field}" year.'
class ProhibitSurrogateCharactersValidator:
"""
Validator that prohibits surrogate characters in text fields.
"""
message = 'Surrogate characters are not allowed.'
code = 'surrogate_characters_not_allowed'
def __call__(self, value):
"""Validate value does not contain surrogate characters."""from rest_framework import serializers
from rest_framework.validators import UniqueValidator, UniqueTogetherValidator
class BookSerializer(serializers.ModelSerializer):
# Unique field validator
isbn = serializers.CharField(
validators=[UniqueValidator(queryset=Book.objects.all())]
)
class Meta:
model = Book
fields = ['title', 'isbn', 'author', 'publication_year']
# Unique together validator
validators = [
UniqueTogetherValidator(
queryset=Book.objects.all(),
fields=['title', 'author'],
message="Book with this title and author already exists."
)
]
# Unique for date validator
class EventSerializer(serializers.ModelSerializer):
class Meta:
model = Event
fields = ['name', 'venue', 'date']
validators = [
UniqueForDateValidator(
queryset=Event.objects.all(),
field='name',
date_field='date',
message="Event name must be unique per date."
)
]
# Custom validator function
def validate_isbn_format(value):
"""Validate ISBN format (basic example)."""
if not value.replace('-', '').isdigit():
raise serializers.ValidationError("ISBN must contain only digits and hyphens")
return value
class BookSerializer(serializers.Serializer):
isbn = serializers.CharField(validators=[validate_isbn_format])from rest_framework import serializers
class BookSerializer(serializers.Serializer):
title = serializers.CharField(max_length=200)
isbn = serializers.CharField(max_length=13, min_length=13)
publication_date = serializers.DateField()
pages = serializers.IntegerField(min_value=1, max_value=10000)
price = serializers.DecimalField(max_digits=6, decimal_places=2)
is_available = serializers.BooleanField(default=True)
# Custom validation
def validate_isbn(self, value):
if not value.isdigit():
raise serializers.ValidationError("ISBN must contain only digits")
return value
def validate(self, data):
if data['publication_date'] > timezone.now().date():
raise serializers.ValidationError("Publication date cannot be in future")
return dataclass AuthorSerializer(serializers.Serializer):
name = serializers.CharField(max_length=100)
email = serializers.EmailField()
website = serializers.URLField(required=False)
bio = serializers.CharField(allow_blank=True)
class BookSerializer(serializers.Serializer):
# Nested object
author = AuthorSerializer()
# List of strings
tags = serializers.ListField(
child=serializers.CharField(max_length=50),
allow_empty=False,
max_length=5
)
# Dictionary with string values
metadata = serializers.DictField(
child=serializers.CharField(),
allow_empty=True
)
# JSON field
settings = serializers.JSONField(default=dict)
# Choice field
genre = serializers.ChoiceField(choices=[
('fiction', 'Fiction'),
('non-fiction', 'Non-Fiction'),
('mystery', 'Mystery'),
])
# File upload
cover_image = serializers.ImageField(required=False)class BookSerializer(serializers.ModelSerializer):
# Computed field using method
full_title = serializers.SerializerMethodField()
# Read-only field
created_by = serializers.ReadOnlyField(source='owner.username')
# Hidden field with default
created_at = serializers.HiddenField(default=timezone.now)
# Current user default
owner = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Book
fields = ['id', 'title', 'author', 'full_title', 'created_by', 'owner']
def get_full_title(self, obj):
return f"{obj.title} by {obj.author.name}"from rest_framework import serializers
def validate_even_number(value):
if value % 2 != 0:
raise serializers.ValidationError("Must be an even number")
return value
class CustomFieldSerializer(serializers.Serializer):
# Field-level validator
even_number = serializers.IntegerField(validators=[validate_even_number])
# Custom field validation method
def validate_title(self, value):
if 'forbidden' in value.lower():
raise serializers.ValidationError("Title contains forbidden word")
return value
# Object-level validation
def validate(self, data):
if data.get('start_date') and data.get('end_date'):
if data['start_date'] >= data['end_date']:
raise serializers.ValidationError("End date must be after start date")
return dataInstall with Tessl CLI
npx tessl i tessl/pypi-djangorestframework