← Blog

Migrate Django models to Prisma schema automatically

Django's ORM is excellent for Python-only stacks, but when a project adds a TypeScript frontend, a Node.js microservice, or a Prisma-managed database layer, the Python model definitions and the new Prisma schema need to describe the same tables. Writing the Prisma schema by hand from Django models is tedious — every CharField(max_length=), DateTimeField(auto_now_add=True), and choices= enum needs to be translated manually, and gaps always sneak in.

SchemaForge converts Django model files to a Prisma schema automatically. One command parses your models.py and writes a Prisma-ready schema.prisma — field types, @db.VarChar constraints, indexes, choices-based enums, and server defaults all included.

Install SchemaForge

# From source (recommended — PyPI publishing pending)
pip install git+https://github.com/Coding-Dev-Tools/schemaforge.git
Not on public PyPI. Use the source-install command above. Requires Python 3.10+.

A typical Django model file

Suppose you have a Django app with users and blog posts:

# models.py
from django.db import models

class User(models.Model):
    STATUS_CHOICES = [
        ("active", "Active"),
        ("suspended", "Suspended"),
        ("deleted", "Deleted"),
    ]

    email = models.EmailField(unique=True)
    username = models.CharField(max_length=60, unique=True)
    status = models.CharField(max_length=20, choices=STATUS_CHOICES, default="active")
    bio = models.TextField(blank=True, default="")
    is_staff = models.BooleanField(default=False)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = "users"
        indexes = [models.Index(fields=["email", "status"])]

class Post(models.Model):
    title = models.CharField(max_length=255)
    slug = models.SlugField(max_length=255, unique=True)
    body = models.TextField()
    author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts")
    published_at = models.DateTimeField(null=True, blank=True)
    view_count = models.PositiveIntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = "posts"

Convert with one command

schemaforge convert --from django --to prisma --input models.py --output schema.prisma

SchemaForge reads the Python source, resolves field types and constraints, maps choices= tuples to Prisma enum blocks, and writes the output schema:

// schema.prisma (generated by SchemaForge v1.7.0)

generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

enum UserStatus {
  active
  suspended
  deleted
}

model User {
  id         Int        @id @default(autoincrement())
  email      String     @unique @db.VarChar(254)
  username   String     @unique @db.VarChar(60)
  status     UserStatus @default(active)
  bio        String     @default("")
  isStaff    Boolean    @default(false)
  createdAt  DateTime   @default(now())
  updatedAt  DateTime   @updatedAt

  posts      Post[]

  @@map("users")
  @@index([email, status])
}

model Post {
  id          Int       @id @default(autoincrement())
  title       String    @db.VarChar(255)
  slug        String    @unique @db.VarChar(255)
  body        String
  authorId    Int
  publishedAt DateTime?
  viewCount   Int       @default(0)
  createdAt   DateTime  @default(now())

  @@map("posts")
}
Foreign-key relations require a manual step. SchemaForge converts field definitions, types, indexes, and enums faithfully. Cross-model ForeignKey and ManyToManyField relations are not yet preserved automatically — you will need to add the @relation block and the inverse side by hand after conversion. This is a known limitation (work in progress for a future release). The column itself (authorId Int) and its index are emitted correctly; only the Prisma @relation(...) directive is missing.

Type fidelity

Django fieldPrisma typeNotes
CharField(max_length=N)String @db.VarChar(N)max_length constraint preserved
TextFieldStringno length cap
EmailFieldString @db.VarChar(254)Django's 254-char default
SlugField(max_length=N)String @db.VarChar(N)
IntegerFieldInt
PositiveIntegerFieldIntpositivity is app-level, not DB-level
BigIntegerFieldBigInt
FloatFieldFloat
DecimalFieldDecimal
BooleanFieldBoolean
DateTimeField(auto_now_add=True)DateTime @default(now())
DateTimeField(auto_now=True)DateTime @updatedAt
DateTimeField(null=True)DateTime?optional
choices= tuple listenum blockenum name derived from field name + model
ForeignKeyInt (column only)@relation directive: manual step required
ManyToManyFieldnot emittedmanual step required
Meta.db_table@@map("...")
Meta.indexes@@index([...])
unique=True@unique

Batch-convert an entire Django app

If your models are split across multiple files (e.g., a models/ package), pass the directory instead:

schemaforge convert --from django --to prisma --input myapp/models/ --output schema.prisma

For multiple input files, use the documented conversion and review process for each generated schema. Foreign-key constraints and ORM relationship fields require manual review after conversion.

Custom type mappings

Django projects often use custom field subclasses or database-specific types. Override the default mapping with a YAML file:

# type-map.yaml
django_to_prisma:
  "models.UUIDField": "String @db.Uuid"
  "models.JSONField": "Json"
  "models.BinaryField": "Bytes"
schemaforge convert --from django --to prisma --input models.py --type-map type-map.yaml

Verify the result with diff

After adjusting the generated schema (adding @relation blocks, tweaking defaults), use schemaforge diff to confirm your edits against the original or a previous version:

schemaforge diff schema-v1.prisma schema-v2.prisma

The diff output shows added, removed, and modified models, fields, and indexes — useful for code review and for auditing how much manual work was needed after the auto-conversion.

VS Code extension

The SchemaForge VS Code extension adds a live preview panel alongside your Django model files: open a models.py, trigger the command palette, and see the Prisma output update as you type. No need to re-run the CLI after every edit during a migration session.

SchemaForge supports 11 formats and 100 documented conversion directions: SQL DDL, Prisma, Drizzle, TypeORM, Django, SQLAlchemy, Alembic, JSON Schema, GraphQL SDL, EF Core C#, and Scala case classes. Alembic is output-only. Prisma does not have to be the destination — you can go Django → Drizzle, Django → GraphQL SDL, or Django → SQL DDL with the same CLI:

schemaforge convert --from django --to drizzle --input models.py
schemaforge convert --from django --to graphql --input models.py --output schema.graphql
schemaforge convert --from django --to sql --input models.py --output schema.sql

Install SchemaForge →


SchemaForge is an MIT-licensed CLI tool built by Coding Dev Tools. The shared representation preserves tables, columns, types, defaults, indexes, unique constraints, and enums. Foreign-key constraints and ORM relationship fields require review after conversion.