Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create a management command to generate the .d.ts file #11

Open
ChickenF622 opened this issue Nov 14, 2020 · 1 comment
Open

Create a management command to generate the .d.ts file #11

ChickenF622 opened this issue Nov 14, 2020 · 1 comment

Comments

@ChickenF622
Copy link

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__
@adenh93
Copy link
Owner

adenh93 commented Nov 27, 2020

Hi @ChickenF622,

Good stuff, this sounds useful!
I'll check this out on the weekend 👍

Thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants