Skip to main content

Add your description here

Project description

Django SchemaForm Logo

Django forms from Pydantic models

PyPI Python License


django-schemaform lets you define your form schema once using Pydantic and get a fully-featured Django form with automatic field mapping, constraints, and validation.

Installation

uv add django-schemaform

Or with pip:

pip install django-schemaform

Quick Start

Define a Pydantic model and create a form:

from pydantic import BaseModel, EmailStr, Field
from schemaform import SchemaForm


class ContactSchema(BaseModel):
    name: str = Field(min_length=2, max_length=100)
    email: EmailStr
    message: str = Field(min_length=10, description="Your message to us")


class ContactForm(SchemaForm):
    class Meta:
        schema = ContactSchema

Use it in your Django view:

from django.shortcuts import render, redirect


def contact_view(request):
    if request.method == "POST":
        form = ContactForm(request.POST)
        if form.is_valid():
            data = form.validated_data  # Pydantic model instance
            # process data...
            return redirect("success")
    else:
        form = ContactForm()
    
    return render(request, "contact.html", {"form": form})

That's it! The form automatically:

  • Maps strCharField, EmailStrEmailField
  • Applies min_length/max_length constraints
  • Uses the description as help text
  • Validates through Pydantic on submit

Field Type Mapping

Core Python Types

Python Type Django Field
str CharField
int IntegerField
float FloatField
bool BooleanField
Decimal DecimalField
date DateField
time TimeField
datetime DateTimeField
timedelta DurationField
UUID UUIDField

Pydantic Types

Pydantic Type Django Field
EmailStr EmailField
HttpUrl URLField
AnyUrl URLField
SecretStr CharField (password widget)
Json JSONField
PastDate DateField
FutureDate DateField
PastDatetime DateTimeField
FutureDatetime DateTimeField

File Upload Types

SchemaForm Type Django Field
FileUpload FileField
ImageUpload ImageField
from schemaform import SchemaForm, FileUpload, ImageUpload

class UploadSchema(BaseModel):
    document: FileUpload
    photo: ImageUpload | None = None  # Optional

Choice Fields

Python Type Django Field
Literal["a", "b", "c"] ChoiceField
enum.Enum subclass ChoiceField
from typing import Literal
from enum import Enum

class Priority(str, Enum):
    LOW = "low"
    MEDIUM = "medium"
    HIGH = "high"

class TaskSchema(BaseModel):
    status: Literal["pending", "done"]
    priority: Priority
    category: Priority | None = None  # Optional - adds empty choice

Constraint Mapping

Pydantic Constraint Django Field Attribute
min_length min_length
max_length max_length
ge / gt min_value
le / lt max_value
max_digits max_digits (Decimal)
decimal_places decimal_places (Decimal)
pattern validators (RegexValidator)

Labels and Help Text

Field metadata from Pydantic is automatically applied:

class ProfileSchema(BaseModel):
    username: str = Field(
        title="Username",           # → label
        description="Choose wisely" # → help_text
    )

Validation

Single-Field Validation

Use Pydantic's @field_validator for field-level validation:

from pydantic import BaseModel, field_validator
from schemaform import SchemaForm, FileUpload


class UploadSchema(BaseModel):
    resume: FileUpload

    @field_validator("resume")
    @classmethod
    def validate_resume(cls, v):
        if v.size > 5 * 1024 * 1024:  # 5MB
            raise ValueError("File must be under 5MB")
        if not v.content_type == "application/pdf":
            raise ValueError("Only PDF files allowed")
        return v

Cross-Field Validation

Use @model_validator for validation across multiple fields:

from pydantic import BaseModel, SecretStr, model_validator
from schemaform import SchemaForm


class RegistrationSchema(BaseModel):
    email: EmailStr
    password: SecretStr = Field(min_length=8)
    password_confirm: SecretStr

    @model_validator(mode="after")
    def passwords_match(self):
        if self.password.get_secret_value() != self.password_confirm.get_secret_value():
            raise ValueError("Passwords do not match")
        return self


class RegistrationForm(SchemaForm):
    class Meta:
        schema = RegistrationSchema

Validation errors are automatically mapped to the appropriate form fields or to __all__ for non-field errors.

Demo Application

A demo Django application is included with example forms showcasing various features:

  • Contact Form — Email, time fields, Literal choices
  • User Registration — SecretStr passwords, PastDate, password matching validation
  • Event Booking — Date/time, Decimal constraints, Enum choices, cross-field validation
  • Product Review — UUID, integer rating with range, optional ImageUpload
  • Job Application — FileUpload with validation, HttpUrl, Enum, Decimal
  • Medical Appointment — FutureDatetime, Enum, sensitive data handling

See demo/README.md for setup instructions.

Requirements

  • Python ≥ 3.12
  • Django ≥ 5.2, < 6.0
  • Pydantic ≥ 2.0, < 3.0

Contributing

Contributions are welcome! See CONTRIBUTING.md for development setup and guidelines.

License

BSD-3-Clause — see LICENSE.md for details.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_schemaform-0.1.1.tar.gz (23.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_schemaform-0.1.1-py3-none-any.whl (25.9 kB view details)

Uploaded Python 3

File details

Details for the file django_schemaform-0.1.1.tar.gz.

File metadata

  • Download URL: django_schemaform-0.1.1.tar.gz
  • Upload date:
  • Size: 23.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_schemaform-0.1.1.tar.gz
Algorithm Hash digest
SHA256 eb8098dcc207857d58659dfde6573972352a3b688de9eb6cd9386fdf57a60fc2
MD5 74f9a772ad2dc39246cee5654be3fca7
BLAKE2b-256 11a9b9b73295121cedb46e58696f96442d6b7e0aa4ced3cadaf8e5ebea6ec3c7

See more details on using hashes here.

File details

Details for the file django_schemaform-0.1.1-py3-none-any.whl.

File metadata

  • Download URL: django_schemaform-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 25.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: uv/0.9.28 {"installer":{"name":"uv","version":"0.9.28","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for django_schemaform-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 c4af0bcef263f4ce0c1ae09833dd217cd58b702dccac2c3d6c95bf384b0f67c1
MD5 00ab4da7b9ad679e4bdd9c278eb341b3
BLAKE2b-256 b2bc874db80bfd9ca7d85b104b913b250cd5d8ebad6aec7df8038e083dca700f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page