I have created my own custom command, and figured it could be of use to other people it currently goes through each installed app checks for serializers and will automatically apply the @ts_interafce decorator to them:
import importlib
import inspect
import os
from types import ModuleType
from django.apps import AppConfig
from django.conf import settings
from django.core.management.base import BaseCommand
from django_typomatic import ts_interface, get_ts
from rest_framework.serializers import Serializer
class Command(BaseCommand):
EXCLUDED_APPS = ['rest_framework']
help = 'Creates a TypeScript definition file for all models registered in DRF serializers under src/ts/@types/django-models.d.ts'
def create_model_mappings(self, app_config: AppConfig):
"""Updates the custom mappings with related models and their type in ts"""
mappings = {}
for model in app_config.get_models():
for field in model._meta.get_fields():
if field.related_model is not None:
ts_type = field.related_model.__name__
if field.many_to_many or field.one_to_many:
ts_type += '[]'
mappings[field.name] = ts_type
return mappings
def handle(self, *args, **options):
from django.apps import apps
for app_config in apps.get_app_configs():
if app_config.name not in self.EXCLUDED_APPS:
self.handle_app_config(app_config)
# Remove Serializer from type name since it's redundant in TS
ts = get_ts().replace('Serializer', '')
type_file_location = os.path.join(settings.BASE_DIR, 'src/ts/@types/django-models.d.ts')
with open(type_file_location, 'w') as type_file:
type_file.write(ts)
self.stdout.write(self.style.SUCCESS(f'Type file sucessfully generated at {type_file_location}'))
def handle_app_config(self, app_config: AppConfig):
try: #Check to see the app has serializers
serializers_module: ModuleType = importlib.import_module(app_config.name + '.serializers')
except ImportError:
return
mappings = self.create_model_mappings(app_config)
serializers = inspect.getmembers(serializers_module, lambda member: self.is_serializer(member, serializers_module))
for name, serializer in serializers:
# Get the class def and apply the ts_interface decorator to it
base_class = getattr(serializers_module, name)
ts_interface(mapping_overrides=mappings)(base_class)
def is_serializer(self, member: object, module):
"""Checks to see if the given member is a serializer class and is a part of the given module"""
return inspect.isclass(member) and issubclass(member, Serializer) and member.__module__ == module.__name__
I have created my own custom command, and figured it could be of use to other people it currently goes through each installed app checks for serializers and will automatically apply the @ts_interafce decorator to them: