Working with Pydapter Fields¶
Field System Overview¶
Pydapter provides a comprehensive field system built on top of Pydantic v2 that includes:
- Field Templates: Reusable field definitions with flexible naming
- Common Templates: Pre-configured templates for common field types (IDs, timestamps, etc.)
- Field Families: Logical groupings of fields for database patterns
- Protocol Families: Field sets that match pydapter protocol requirements
- Validation Patterns: Common regex patterns and constraint builders
- Domain Model Builder: Fluent API for creating models
Field Templates¶
Field templates are reusable field definitions that can be customized for different contexts:
from pydapter.fields import FieldTemplate
# Define a reusable template
name_template = FieldTemplate(
base_type=str,
description="Name field",
min_length=1,
max_length=100
)
# Use in models with different field names
from pydapter.fields import create_model
User = create_model(
"User",
fields={
"username": name_template.create_field("username"),
"full_name": name_template.create_field("full_name")
}
)
Common Field Templates¶
Pydapter provides pre-configured templates for common field types:
from pydapter.fields import (
ID_TEMPLATE,
CREATED_AT_TEMPLATE,
UPDATED_AT_TEMPLATE,
EMAIL_TEMPLATE,
URL_TEMPLATE,
JSON_TEMPLATE,
TAGS_TEMPLATE
)
# Using templates in model creation
fields = {
"id": ID_TEMPLATE.create_field("id"),
"email": EMAIL_TEMPLATE.create_field("email"),
"website": URL_TEMPLATE.create_field("website"),
"tags": TAGS_TEMPLATE.create_field("tags")
}
User = create_model("User", fields=fields)
Field Families¶
Field families are logical groupings of fields for common database patterns:
from pydapter.fields import FieldFamilies, create_field_dict, create_model
# Core families available:
# - ENTITY: id, created_at, updated_at
# - ENTITY_TZ: Same but with timezone-aware timestamps
# - SOFT_DELETE: deleted_at, is_deleted
# - AUDIT: created_by, updated_by, version
# Combine families to create models
fields = create_field_dict(
FieldFamilies.ENTITY,
FieldFamilies.AUDIT,
FieldFamilies.SOFT_DELETE
)
AuditedEntity = create_model("AuditedEntity", fields=fields)
Domain Model Builder¶
The DomainModelBuilder provides a fluent API for creating models:
from pydapter.fields import DomainModelBuilder, FieldTemplate
# Build a model with method chaining
TrackedEntity = (
DomainModelBuilder("TrackedEntity")
.with_entity_fields(timezone_aware=True)
.with_soft_delete(timezone_aware=True)
.with_audit_fields()
.add_field("name", FieldTemplate(
base_type=str,
description="Entity name",
max_length=100
))
.add_field("status", FieldTemplate(
base_type=str,
default="active",
description="Entity status"
))
.build()
)
Protocol Field Families¶
For models that need to implement pydapter protocols:
from pydapter.fields import create_protocol_model, FieldTemplate
# Create a model implementing multiple protocols
Document = create_protocol_model(
"Document",
"identifiable", # Adds id field
"temporal", # Adds created_at, updated_at
"embeddable", # Adds embedding field
"cryptographical", # Adds sha256 field
timezone_aware=True,
# Add custom fields
title=FieldTemplate(base_type=str, description="Document title"),
content=FieldTemplate(base_type=str, description="Document content")
)
Validation Patterns¶
Use pre-built validation patterns for common field types:
from pydapter.fields import (
ValidationPatterns,
create_pattern_template,
create_range_template
)
# Use pre-defined patterns
slug_field = create_pattern_template(
ValidationPatterns.SLUG,
description="URL-friendly slug",
error_message="Must contain only lowercase letters, numbers, and hyphens"
)
phone_field = create_pattern_template(
ValidationPatterns.US_PHONE,
description="US phone number"
)
# Create range-constrained fields
percentage = create_range_template(
float,
ge=0,
le=100,
description="Percentage value"
)
age = create_range_template(
int,
ge=0,
le=150,
description="Person's age"
)
Field Template Modifiers¶
Field templates support transformation methods:
from pydapter.fields import ID_TEMPLATE, EMAIL_TEMPLATE
# Make fields nullable
nullable_id = ID_TEMPLATE.as_nullable()
optional_email = EMAIL_TEMPLATE.as_nullable()
# Copy with modifications
custom_id = ID_TEMPLATE.copy(
description="Custom identifier",
frozen=False # Make it mutable
)
# Change field properties
long_description = FieldTemplate(
base_type=str,
max_length=1000
).copy(max_length=2000)
Complete Example¶
Here's a comprehensive example combining the field system features:
from pydapter.fields import (
DomainModelBuilder,
FieldTemplate,
create_protocol_model,
create_pattern_template,
ValidationPatterns
)
# 1. Using DomainModelBuilder
BlogPost = (
DomainModelBuilder("BlogPost")
.with_entity_fields(timezone_aware=True)
.with_soft_delete()
.with_audit_fields()
.add_field("title", FieldTemplate(
base_type=str,
description="Post title",
max_length=200
))
.add_field("slug", create_pattern_template(
ValidationPatterns.SLUG,
description="URL slug"
))
.add_field("content", FieldTemplate(
base_type=str,
description="Post content"
))
.build()
)
# 2. Using Protocol Models
EmbeddableDocument = create_protocol_model(
"EmbeddableDocument",
"identifiable",
"temporal",
"embeddable",
title=FieldTemplate(base_type=str),
content=FieldTemplate(base_type=str),
tags=FieldTemplate(
base_type=list[str],
default_factory=list
)
)
# 3. Custom field family
custom_family = {
"name": FieldTemplate(base_type=str, max_length=100),
"email": EMAIL_TEMPLATE,
"is_active": FieldTemplate(base_type=bool, default=True)
}
CustomModel = (
DomainModelBuilder("CustomModel")
.with_entity_fields()
.with_family(custom_family)
.build()
)
Key Design Principles¶
- Templates over instances: Field templates can be reused across multiple fields
- Composition over inheritance: Build complex models by combining families
- Protocol alignment: Use protocol families for models that implement pydapter protocols
- Validation patterns: Leverage pre-built patterns for common validation needs
- Fluent API: Use method chaining for readable model construction
The field system provides a foundation for creating consistent, validated data models that integrate seamlessly with pydapter's adapter ecosystem.