MetaPhase-Consulting/State-TalentMAP-API

View on GitHub
talentmap_api/common/renderers.py

Summary

Maintainability
A
0 mins
Test Coverage
from django import forms
from django.core.paginator import Page

from rest_framework.renderers import BrowsableAPIRenderer
from rest_framework.request import override_method
from rest_framework_csv.renderers import CSVRenderer


class PaginatedCSVRenderer(CSVRenderer):
    '''
    Modified from https://github.com/mjumbewu/django-rest-framework-csv
    Supports CSV rendering on paginated views
    '''
    results_field = 'results'

    def render(self, data, *args, **kwargs):
        '''
        We need the handle the following cases:
            1. Paginated endpoint
                 {
                    page_metadata
                    results: [<RENDERABLES>]
                 }
            2. Non-paginated list endpoints
                [<RENDERABLES>]
            3. Single-object retrieve endpoints
                <RENDERABLE>
        '''

        '''
        In case 2, we don't need to do anything
        In cases 1 & 3, the data is not a list, so we check for that here
        '''
        if not isinstance(data, list):
            '''
            In case 1, we have a data[results_field] array, so that is returned
            In case 3, we don't, so we hit the default of creating an array with
            a single item, the retrieved object
            '''
            data = data.get(self.results_field, [data])
        return super(PaginatedCSVRenderer, self).render(data, *args, **kwargs)


class BrowsableAPIRendererWithoutForms(BrowsableAPIRenderer):
    """Renders the browsable api, but excludes the HTML form."""

    def get_rendered_html_form(self, data, view, method, request):
        """Don't render the HTML form"""
        return None

    # Lifted from the DRF, but modified to remove content + HTML form
    def get_raw_data_form(self, data, view, method, request):
        """
        Returns a form that allows for arbitrary content types to be tunneled
        via standard HTML forms.
        (Which are typically application/x-www-form-urlencoded)
        Modifications: Set content to None so this doesn't bombard the database
        """
        serializer = getattr(data, 'serializer', None)
        if serializer and not getattr(serializer, 'many', False):
            instance = getattr(serializer, 'instance', None)
            if isinstance(instance, Page):
                instance = None
        else:
            instance = None

        with override_method(view, request, method) as request:
            # Check permissions
            if not self.show_form_for_method(view, method, request, instance):
                return

            # Generate a generic form that includes a content type field,
            # and a content field.
            media_types = [parser.media_type for parser in view.parser_classes]

            class GenericContentForm(forms.Form):
                _content_type = forms.ChoiceField(
                    label='Media type',
                    choices=[(media_type, media_type) for media_type in media_types],
                    initial=media_types[0],
                    widget=forms.Select(attrs={'data-override': 'content-type'})
                )
                _content = forms.CharField(
                    label='Content',
                    widget=forms.Textarea(attrs={'data-override': 'content'}),
                    initial=None
                )

            return GenericContentForm()