Sunday, 24 March 2019

Defining an API for a complex function (function generates classes with a large amount of configurable parameters)

I'm writing a view generator for my Django project. I have a large number of models from a legacy application (~150 models), that all need the same basic CRUD operations (providing Admin access isn't enough apparently).

So I'm writing a generator that returns 5 Views for each model, and of course each view can potentially take a large number of options, and I'm trying to define sane API/default parameter format for my generator.

My current generator:

def generate_views(model_class, **kwargs):
    """
    For a given model, returns a dict of generic class-based views
    """
    ###
    # Forms
    #   Optionally generate form classes if not already provided
    ###

    # Append these fields with either "create_" or "update_" to have them only
    # apply to that specific type of form
    form_override_args = ['fields', 'exclude', 'form_method', 'form_class',
                          'form_layout', 'widgets', 'media_css', 'media_js']

    if 'form_class' not in kwargs and 'create_form_class' not in kwargs:
        create_form_kwargs = kwargs.copy()
        for arg in form_override_args:
            if f'create_{arg}' in kwargs:
                create_form_kwargs[arg] = kwargs[f'create_{arg}']
        kwargs['create_form_class'] = forms.FormFactory(model_class, **create_form_kwargs).form()

    if 'form_class' not in kwargs and 'update_form_class' not in kwargs:
        update_form_kwargs = kwargs.copy()
        for arg in form_override_args:
            if f'update_{arg}' in kwargs:
                update_form_kwargs[arg] = kwargs[f'update_{arg}']
        kwargs['update_form_class'] = forms.FormFactory(model_class, **update_form_kwargs).form()

    if 'form_class' not in kwargs:
        kwargs['form_class'] = forms.FormFactory(model_class, **kwargs).form()

    ###
    # Tables
    #   Optionally generate table classes if not already provided
    ###

    # Append these fields with "table_" to have them only
    # apply to the table view
    table_override_args = ['fields', 'exclude']

    if 'table_class' not in kwargs:
        update_table_kwargs = kwargs.copy()
        for arg in table_override_args:
            if f'table_{arg}' in kwargs:
                update_table_kwargs[arg] = kwargs[f'table_{arg}']
        kwargs['table_class'] = tables.TableFactory(model_class, **update_table_kwargs).table()

    ###
    # Views
    #   Generate 5 generic views based on the provided model
    ###
    view_factory = views.ViewFactory(model_class, **kwargs)

    return {
        'list_view': view_factory.list_view(),
        'detail_view': view_factory.detail_view(),
        'create_view': view_factory.create_view(),
        'update_view': view_factory.update_view(),
        'delete_view': view_factory.delete_view()
    }

I'm currently relying on kwargs, and I wanted to define what a fully filled-out kwargs dict should look like. Something like

{
    'forms': {
        'all': {

        },
        'create': {

        },
        'update': {

        }
    },
    'tables': {
        'all': {

        },
        'list': {

        }
    },
    'views': {
        'all': {

        },
        'list': {

        },
        'detail': {

        },
        'create': {

        },
        'update': {

        },
        'delete': {

        }
    }
}

And it's just seeming a bit overworked. I'm mostly looking for recommendations on a potentially better design (because I'm going cross eyed from just working on it).



from Defining an API for a complex function (function generates classes with a large amount of configurable parameters)

No comments:

Post a Comment