Skip to main content

A simple solution for generating Typescript interfaces from your Django Rest Framework Serializers.

Project description

django-typomatic pypi badge

A simple solution for generating Typescript interfaces from your Django Rest Framework Serializers.

Since I now require a simple package to generate Typescript interfaces for Django Rest Framework serializers, I've decided to port over my Typemallow package for use with DRF serializers!

Usage:

Using django-typomatic is just as simple!

First, install the package pip install django-typomatic

Option 1: Decorators

For your Django Rest Framework serializers that you wish to generate Typescript interfaces for, simply import ts_interface and generate_ts from the django_typomatic module, and add the @ts_interface() class decorator to your Django Rest Framework serializer class.

All that is required to generate your Typescript interfaces is to call the generate_ts() function, and provide a filepath as a parameter to output the result.

main.py

from django_typomatic import ts_interface, generate_ts
from rest_framework import serializers


@ts_interface()
class Foo(serializers.Serializer):
    some_field = serializers.CharField()
    another_field = serializers.DateTimeField()


generate_ts('./output.ts')

output.ts

export interface Foo {
  some_field: string;
  another_field: date;
}

Alternatively, you can call get_ts(), which will return the generated interfaces as a raw string, rather than writing the results to a file:

main.py

from django_typomatic import ts_interface, get_ts
from rest_framework import serializers


@ts_interface()
class Foo(serializers.Serializer):
    some_field = serializers.ListField(child=serializers.IntegerField())
    another_field = serializers.CharField()

print(get_ts())

which outputs the following string:

export interface Foo {\n some_field: number[];\n another_field: string;\n}\n\n

django-typomatic supports nested serializers, as well as list fields and other fields that act as lists (any field with many=True)

main.py

from django_typomatic import ts_interface, generate_ts
from rest_framework import serializers


@ts_interface()
class Foo(serializers.Serializer):
    some_field = serializers.ListField(child=serializers.IntegerField())
    another_field = serializers.CharField()


@ts_interface()
class Bar(serializers.Serializer):
    foo = Foo()
    foos = Foo(many=True)
    bar_field = serializers.CharField()

output.ts

export interface Foo {
  some_field: number[];
  another_field: string;
}

export interface Bar {
  foo: Foo;
  foos: Foo[];
  bar_field: string;
}

django-typomatic also supports ChoiceField serializers, as well as any other serializer fields that makes use of choices.

main.py

from django_typomatic import ts_interface
from rest_framework import serializers
from django.db import models


class ActionType(models.TextChoices):
    ACTION1 = "Action1", ("Action1")
    ACTION2 = "Action2", ("Action2")
    ACTION3 = "Action3", ("Action3")


class NumberType(models.IntegerChoices):
    LOW = 1
    MEDIUM = 2
    HIGH = 3


@ts_interface('choices')
class ChoiceSerializer(serializers.Serializer):
    action = serializers.ChoiceField(choices=ActionType.choices)
    num = serializers.ChoiceField(choices=NumberType.choices)

output.ts

export interface ActionSerializer {
  action: "Action1" | "Action2" | "Action3";
  num: 1 | 2 | 3;
}

Extended Usage:

The @ts_interface() decorator function accepts an optional parameter, context, which defaults to... well... 'default'.

"Why is this the case?"

When a Serializer is identified with with @ts_interface decorator, it is added to a list in a dictionary of serializers, with the dictionary key being the value provided to the context parameter. If you were to provide different contexts for each serializer, additional keys will be created if they do not exist, or the serializer will simply be appended to the list at the existing key.

This comes in handy, as the generate_ts() function also accepts an optional context parameter, which will filter only serializers in the dictionary at the specific key.

This is useful if you wish to output different contexts to different files, e.g.

main.py

...
from django_typomatic import ts_interface, generate_ts
from rest_framework import serializers


@ts_interface(context='internal')
class Foo(serializers.Serializer):
    foo = serializers.CharField()


@ts_interface(context='internal')
class Bar(serializers.Serializer):
    bar = serializers.CharField()


@ts_interface(context='external')
class FooBar(serializers.Serializer):
    foo_bar = serializers.CharField()


'''
we're telling django-typomatic that we only want to generate interfaces from serializers with
an 'internal' context to './internal.ts'
'''
generate_ts('./internal.ts', context='internal')

'''
only generate interfaces from serializers with an 'external' context to './external.ts'
'''
generate_ts('./external.ts', context='external')

internal.ts

export interface Foo {
  foo: string;
}

export interface Bar {
  bar: string;
}

external.ts

export interface FooBar {
  foo_bar: string;
}

Camelize

You can use django dependencies that converts the response from snake_casing to camelCasing. The solution offered for this is camelize:

from django_typomatic import ts_interface, generate_ts
from rest_framework import serializers


@ts_interface()
class Foo(serializers.Serializer):
    some_field = serializers.CharField()


generate_ts('./output.ts', camelize=True)

Different from the main example. The interface attributes are now camel casing.

output.ts

export interface Foo {
  someField: string;
}

TypeScript enums from ChoiceFields

django-typomatic also allows for generating an enum for a ChoiceField. The enum will follow the naming of ModelFieldNameChoiceEnum for a model field with the name model_field_name, note that the interface field still remains model_field_name.

main.py

from django_typomatic import ts_interface
from rest_framework import serializers
from django.db import models


class ActionType(models.TextChoices):
    ACTION1 = "Action1", ("Action1")
    ACTION2 = "Action2", ("Action2")
    ACTION3 = "Action3", ("Action3")


class NumberType(models.IntegerChoices):
    LOW = 1
    MEDIUM = 2
    HIGH = 3


@ts_interface('enumChoices')
class ChoiceSerializer(serializers.Serializer):
    action = serializers.ChoiceField(choices=ActionType.choices)
    num = serializers.ChoiceField(choices=NumberType.choices)

output.ts

export enum ActionChoiceEnum {
    ACTION1 = 'Action1',
    ACTION2 = 'Action2',
    ACTION3 = 'Action3',
}

export enum NumChoiceEnum {
    LOW = 1,
    MEDIUM = 2,
    HIGH = 3,
}


export interface EnumChoiceSerializer {
    action: ActionChoiceEnum;
    num: NumChoiceEnum;
}

Option 2: CLI (Preferred)

Since version 2.1, you can now generate all interfaces via a CLI. This will be the preferred method going forward, as you will no longer need to decorate your serializers, or manually call the generate_ts function, resulting in less complexity overall.

NOTE: In order to use the CLI, you will need to add django_typomatic to INSTALLED_APPS.

Special thanks to @bigpe for brewing up the first version of this CLI!

Usage

--serializers [SERIALIZERS ...], -s [SERIALIZERS ...]
                         Serializers enumeration formats: module_name.SerializerName | module_name
   --all Generate TS types for all project serializers
   --trim, -t Trim "serializer" from type name
   --camelize, -c Camelize field names
   --annotations, -a Add js doc annotations for validations (eg. for Zod)
   --enum_choices, -ec Add choices to external enum type instead union
   --enum_values, -ev Add enum to obtain display name for choices field
   --enum_keys, -ev Add enum to obtain the choices field keys by values

Using the new generate_ts management command, you can fine tune the generation of your interfaces similarly to how you would via the decorator method, with some additional functionality. For example, you can call the command with the --all flag and get all the generated types to the folder specified (they will be grouped by the application name, all external applications will be excluded, only the project applications).

You can also generate modules separately, as an example, -s user will restrict generation to all serializers in the user application, and -s user.UserSerializer will restrict generation to just the UserSerializer serializer belonging to the user application.

Examples

Generate TS for user app

./manage.py generate_ts --app_name user

Generate TS for specific serializer from user app

./manage.py generate_ts -s user.UserSerializer

Generate TS for many apps or serializers

./manage.py generate_ts -s user.UserSerializer group role.RoleSerializer role.RoleListSerializer

Generate TS for user app with annotations, choices enums, trim serializer, camelize, enum values and custom output path

./manage.py generate_ts --app_name user -a -ec -t -c -ev -o "./custom_folder/"

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_typomatic-2.5.2.tar.gz (17.4 kB view details)

Uploaded Source

Built Distribution

django_typomatic-2.5.2-py3-none-any.whl (17.3 kB view details)

Uploaded Python 3

File details

Details for the file django_typomatic-2.5.2.tar.gz.

File metadata

  • Download URL: django_typomatic-2.5.2.tar.gz
  • Upload date:
  • Size: 17.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.0 CPython/3.12.4

File hashes

Hashes for django_typomatic-2.5.2.tar.gz
Algorithm Hash digest
SHA256 8d6a8b8d82e5782756a16b93b8c6004af4a6743b8cb38d520c3fd1588f0f5b82
MD5 b50732d2ed70a3320a75e6457c86ef19
BLAKE2b-256 9dba862af1e6b3e80a3b118d26a1638367c73f0c262d8827456614ee11580b42

See more details on using hashes here.

File details

Details for the file django_typomatic-2.5.2-py3-none-any.whl.

File metadata

File hashes

Hashes for django_typomatic-2.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 9b3a28fd5eb60f48aae0530e5db18d40d6a8c4b869dedb05f214de575a20d11c
MD5 153b757f85fee291af10dd9f31c3dd1b
BLAKE2b-256 5fb365eee687447a49b6d59b21eafa7e1605b90126aa149d3987abfb1d9a05d9

See more details on using hashes here.

Supported by

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