def get_rendered_html_form(self, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        with override_method(view, request, method) as request:
            obj = getattr(view, 'object', None)
            if not self.show_form_for_method(view, method, request, obj):
                return

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            if (not getattr(view, 'get_serializer', None) or not any(
                    is_form_media_type(parser.media_type)
                    for parser in view.parser_classes)):
                return

            serializer = view.get_serializer(instance=obj)

            data = serializer.data
            form_renderer = self.form_renderer_class()
            return form_renderer.render(data, self.accepted_media_type,
                                        self.renderer_context)
Exemplo n.º 2
0
    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)
        """
        # See issue #2089 for refactoring this.
        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

            # If possible, serialize the initial content for the generic form
            default_parser = view.parser_classes[0]
            renderer_class = getattr(default_parser, 'renderer_class', None)
            if (hasattr(view, 'get_serializer') and renderer_class):
                # View has a serializer defined and parser class has a
                # corresponding renderer that can be used to render the data.

                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance)
                else:
                    serializer = view.get_serializer()

                # Render the raw data content
                renderer = renderer_class()
                accepted = self.accepted_media_type
                context = self.renderer_context.copy()
                context['indent'] = 4
                content = renderer.render(serializer.data, accepted, context)
            else:
                content = None

            # 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]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            class GenericContentForm(forms.Form):
                _content_type = forms.ChoiceField(
                    label='Media type',
                    choices=choices,
                    initial=initial,
                    widget=forms.Select(
                        attrs={'data-override': 'content-type'}))
                _content = forms.CharField(
                    label='Content',
                    widget=forms.Textarea(attrs={'data-override': 'content'}),
                    initial=content)

            return GenericContentForm()
Exemplo n.º 3
0
    def get_rendered_html_form(self, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        if request.method == method:
            data = request.DATA
            files = request.FILES
        else:
            data = None
            files = None

        with override_method(view, request, method) as request:
            obj = getattr(view, 'object', None)
            if not self.show_form_for_method(view, method, request, obj):
                return

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            if (not getattr(view, 'get_serializer', None)
                or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)):
                return

            serializer = view.get_serializer(instance=obj, data=data, files=files)
            serializer.is_valid()
            data = serializer.data

            form_renderer = self.form_renderer_class()
            return form_renderer.render(data, self.accepted_media_type, self.renderer_context)
Exemplo n.º 4
0
    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        # See issue #2089 for refactoring this.
        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

        # If this is valid serializer data, and the form is for the same
        # HTTP method as was used in the request then use the existing
        # serializer instance, rather than dynamically creating a new one.
        if request.method == method and serializer is not None:
            try:
                data = request.data
            except ParseError:
                data = None
            existing_serializer = serializer
        else:
            data = None
            existing_serializer = None

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

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            if (
                not getattr(view, 'get_serializer', None)
                or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)
            ):
                return

            if existing_serializer is not None:
                serializer = existing_serializer
            else:
                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance, data=data)
                else:
                    serializer = view.get_serializer(data=data)
                if data is not None:
                    serializer.is_valid()
            form_renderer = self.form_renderer_class()
            return form_renderer.render(
                serializer.data,
                self.accepted_media_type,
                dict(
                    list(self.renderer_context.items()) +
                    [('template', 'rest_framework/api_form.html')]
                )
            )
Exemplo n.º 5
0
    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        # See issue #2089 for refactoring this.
        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

        # If this is valid serializer data, and the form is for the same
        # HTTP method as was used in the request then use the existing
        # serializer instance, rather than dynamically creating a new one.
        if request.method == method and serializer is not None:
            try:
                kwargs = {'data': request.data}
            except ParseError:
                kwargs = {}
            existing_serializer = serializer
        else:
            kwargs = {}
            existing_serializer = None

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

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            if (not getattr(view, 'get_serializer', None) or not any(
                    is_form_media_type(parser.media_type)
                    for parser in view.parser_classes)):
                return

            if existing_serializer is not None:
                serializer = existing_serializer
            else:
                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance,
                                                     **kwargs)
                else:
                    serializer = view.get_serializer(**kwargs)

            if hasattr(serializer, 'initial_data'):
                serializer.is_valid()

            form_renderer = self.form_renderer_class()
            return form_renderer.render(
                serializer.data, self.accepted_media_type,
                dict(
                    list(self.renderer_context.items()) +
                    [('template', 'rest_framework/api_form.html')]))
Exemplo n.º 6
0
    def get_rendered_html_form(self, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        if request.method == method:
            try:
                data = request.DATA
                files = request.FILES
            except ParseError:
                data = None
                files = None
        else:
            data = None
            files = None

        with override_method(view, request, method) as request:
            obj = getattr(view, 'object', None)
            if not self.show_form_for_method(view, method, request, obj):
                return

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            if (not getattr(view, 'get_serializer', None) or not any(
                    is_form_media_type(parser.media_type)
                    for parser in view.parser_classes)):
                return
            # try loading the partial data
            serializer = view.get_serializer(instance=obj,
                                             data=data,
                                             files=files)
            data_complete = serializer.is_valid()
            data = serializer.data
            if not data_complete:
                for k, f in serializer.fields.iteritems():
                    if k in data and k in request.GET:
                        try:
                            if type(data[k]) == list:
                                x = list()
                                for i in request.GET.getlist(k):
                                    try:
                                        x.append(f.from_native(i).id)
                                    except:
                                        pass
                            else:
                                x = f.from_native(request.GET.get(k))
                            data[k] = x
                            data.fields[k]._value = x
                        except Exception:
                            pass
            form_renderer = self.form_renderer_class()
            return form_renderer.render(data, self.accepted_media_type,
                                        self.renderer_context)
Exemplo n.º 7
0
    def test_action_reflect_http_method(self):
        request = self.factory.get()

        view = self.view_class()
        view.action_map = {'get': 'retrieve'}

        # reproduce DRF wrapping
        with override_method(view, Request(request), 'GET') as request:
            view.dispatch(request)
            self.assertEqual(view.action, 'retrieve')
Exemplo n.º 8
0
    def test_action_reflect_http_method(self):
        request = self.factory.get()

        view = self.view_class()
        view.action_map = {'get': 'retrieve'}

        # reproduce DRF wrapping
        with override_method(view, Request(request), 'GET') as request:
            view.dispatch(request)
            self.assertEqual(view.action, 'retrieve')
Exemplo n.º 9
0
    def get_rendered_html_form(self, data, view, method, request):
        old_serializer = getattr(data, 'serializer', None)
        if old_serializer and not getattr(old_serializer, 'many', False):
            instance = getattr(old_serializer, 'instance', None)
            if isinstance(instance, Page):
                instance = None
        else:
            instance = None

        if request.method == method and old_serializer is not None:
            try:
                kwargs = {'data': request.data}
            except ParseError:
                kwargs = {}
        else:
            kwargs = {}

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

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            has_serializer = getattr(view, 'get_serializer', None)

            if ((not has_serializer) or not any(
                    is_form_media_type(parser.media_type)
                    for parser in view.parser_classes)):
                return

            if has_serializer:
                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance,
                                                     method=method,
                                                     **kwargs)
                else:
                    try:
                        serializer = view.get_serializer(method=method,
                                                         **kwargs)
                    except TypeError:
                        serializer = view.get_serializer(**kwargs)
            else:
                # at this point we must have a serializer_class
                if method in ('PUT', 'PATCH'):
                    serializer = self._get_serializer(view.serializer_class,
                                                      view,
                                                      request,
                                                      instance=instance,
                                                      **kwargs)
                else:
                    serializer = self._get_serializer(view.serializer_class,
                                                      view, request, **kwargs)

            return self.render_form_for_serializer(serializer)
Exemplo n.º 10
0
    def get_rendered_html_form(self, data, view, method, request):
        old_serializer = getattr(data, 'serializer', None)
        if old_serializer and not getattr(old_serializer, 'many', False):
            instance = getattr(old_serializer, 'instance', None)
            if isinstance(instance, Page):
                instance = None
        else:
            instance = None

        if request.method == method and old_serializer is not None:
            try:
                kwargs = {'data': request.data}
            except ParseError:
                kwargs = {}
        else:
            kwargs = {}

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

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            has_serializer = getattr(view, 'get_serializer', None)

            if (
                (not has_serializer) or
                not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)
            ):
                return

            if has_serializer:
                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance, method=method, **kwargs)
                else:
                    try:
                        serializer = view.get_serializer(method=method, **kwargs)
                    except TypeError:
                        serializer = view.get_serializer(**kwargs)
            else:
                # at this point we must have a serializer_class
                if method in ('PUT', 'PATCH'):
                    serializer = self._get_serializer(view.serializer_class, view,
                                                      request, instance=instance, **kwargs)
                else:
                    serializer = self._get_serializer(view.serializer_class, view,
                                                      request, **kwargs)

            return self.render_form_for_serializer(serializer)
Exemplo n.º 11
0
    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        # See issue #2089 for refactoring this.
        serializer = getattr(data, 'serializer', None)
        if serializer and not getattr(serializer, 'many', False):
            instance = getattr(serializer, 'instance', None)
        else:
            instance = None

        if request.method == method:
            try:
                data = request.data
            except ParseError:
                data = None
            existing_serializer = serializer
        else:
            data = None
            existing_serializer = None

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

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            if (not getattr(view, 'get_serializer', None) or not any(
                    is_form_media_type(parser.media_type)
                    for parser in view.parser_classes)):
                return

            if existing_serializer is not None:
                serializer = existing_serializer
            else:
                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance,
                                                     data=data)
                else:
                    serializer = view.get_serializer(data=data)
                if data is not None:
                    serializer.is_valid()
            form_renderer = self.form_renderer_class()
            return form_renderer.render(serializer.data,
                                        self.accepted_media_type,
                                        self.renderer_context)
Exemplo n.º 12
0
 def get_rendered_html_form(self, data, view, method, request):
     # Never show auto-generated form (only raw form).
     obj = getattr(view, 'object', None)
     if obj is None and hasattr(view, 'get_object') and hasattr(view, 'retrieve'):
         try:
             view.object = view.get_object()
             obj = view.object
         except Exception:
             obj = None
     with override_method(view, request, method) as request:
         if not self.show_form_for_method(view, method, request, obj):
             return
         if method in ('DELETE', 'OPTIONS'):
             return True  # Don't actually need to return a form
Exemplo n.º 13
0
    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        # See issue #2089 for refactoring this.
        serializer = getattr(data, 'serializer', None)
        if serializer and not getattr(serializer, 'many', False):
            instance = getattr(serializer, 'instance', None)
        else:
            instance = None

        if request.method == method:
            try:
                data = request.data
            except ParseError:
                data = None
            existing_serializer = serializer
        else:
            data = None
            existing_serializer = None

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

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            if (
                not getattr(view, 'get_serializer', None)
                or not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)
            ):
                return

            if existing_serializer is not None:
                serializer = existing_serializer
            else:
                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance, data=data)
                else:
                    serializer = view.get_serializer(data=data)
                if data is not None:
                    serializer.is_valid()
            form_renderer = self.form_renderer_class()
            return form_renderer.render(serializer.data, self.accepted_media_type, self.renderer_context)
Exemplo n.º 14
0
    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
        """
        # See issue #2089 for refactoring this.
        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

            # If possible, serialize the initial content for the generic form
            default_parser = view.parser_classes[0]
            renderer_class = getattr(default_parser, 'renderer_class', None)
            content = None

            # 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]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            class GenericContentForm(forms.Form):
                _content_type = forms.ChoiceField(
                    label='Media type',
                    choices=choices,
                    initial=initial,
                    widget=forms.Select(attrs={'data-override': 'content-type'})
                )
                _content = forms.CharField(
                    label='Content',
                    widget=forms.Textarea(attrs={'data-override': 'content'}),
                    initial=content
                )

            return GenericContentForm()
Exemplo n.º 15
0
    def render(self, data, accepted_media_type=None, renderer_context=None):
        self.accepted_media_type = accepted_media_type or ''
        self.renderer_context = renderer_context or {}

        response = renderer_context['response']
        request = renderer_context['request']
        view = self.renderer_context['view']

        if response.status_code == status.HTTP_400_BAD_REQUEST:
            # Errors still need to display the list or detail information.
            # The only way we can get at that is to simulate a GET request.
            self.error_form = self.get_rendered_html_form(
                data, view, request.method, request)
            self.error_title = {
                'POST': 'Create',
                'PUT': 'Edit'
            }.get(request.method, 'Errors')

            with override_method(view, request, 'GET') as request:
                response = view.get(request, *view.args, **view.kwargs)
            data = response.data

        template = loader.get_template(self.template)
        context = self.get_context(data, accepted_media_type, renderer_context)
        ret = template_render(template,
                              context,
                              request=renderer_context['request'])

        # Creation and deletion should use redirects in the admin style.
        if (response.status_code == status.HTTP_201_CREATED) and ('Location'
                                                                  in response):
            response.status_code = status.HTTP_303_SEE_OTHER
            response['Location'] = request.build_absolute_uri()
            ret = ''

        if response.status_code == status.HTTP_204_NO_CONTENT:
            response.status_code = status.HTTP_303_SEE_OTHER
            try:
                # Attempt to get the parent breadcrumb URL.
                response['Location'] = self.get_breadcrumbs(request)[-2][1]
            except KeyError:
                # Otherwise reload current URL to get a 'Not Found' page.
                response['Location'] = request.full_path
            ret = ''

        return ret
    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
        """
        # See issue #2089 for refactoring this.
        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

            content = None

            # 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]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            class GenericContentForm(forms.Form):
                _content_type = forms.ChoiceField(
                    label='Media type',
                    choices=choices,
                    initial=initial,
                    widget=forms.Select(attrs={'data-override': 'content-type'})
                )
                _content = forms.CharField(
                    label='Content',
                    widget=forms.Textarea(attrs={'data-override': 'content'}),
                    initial=content
                )

            return GenericContentForm()
Exemplo n.º 17
0
    def render(self, data, accepted_media_type=None, renderer_context=None):
        self.accepted_media_type = accepted_media_type or ""
        self.renderer_context = renderer_context or {}

        response = renderer_context["response"]
        request = renderer_context["request"]
        view = self.renderer_context["view"]

        if response.status_code == status.HTTP_400_BAD_REQUEST:
            # Errors still need to display the list or detail information.
            # The only way we can get at that is to simulate a GET request.
            self.error_form = self.get_rendered_html_form(
                data, view, request.method, request)
            self.error_title = {
                "POST": "Create",
                "PUT": "Edit"
            }.get(request.method, "Errors")

            with override_method(view, request, "GET") as request:
                response = view.get(request, *view.args, **view.kwargs)
            data = response.data

        template = loader.get_template(self.template)
        context = self.get_context(data, accepted_media_type, renderer_context)
        ret = template.render(context, request=renderer_context["request"])

        # Creation and deletion should use redirects in the admin style.
        if response.status_code == status.HTTP_201_CREATED and "Location" in response:
            response.status_code = status.HTTP_303_SEE_OTHER
            response["Location"] = request.build_absolute_uri()
            ret = ""

        if response.status_code == status.HTTP_204_NO_CONTENT:
            response.status_code = status.HTTP_303_SEE_OTHER
            try:
                # Attempt to get the parent breadcrumb URL.
                response["Location"] = self.get_breadcrumbs(request)[-2][1]
            except KeyError:
                # Otherwise reload current URL to get a 'Not Found' page.
                response["Location"] = request.full_path
            ret = ""

        return ret
Exemplo n.º 18
0
    def render(self, data, accepted_media_type=None, renderer_context=None):
        self.accepted_media_type = accepted_media_type or ''
        self.renderer_context = renderer_context or {}

        response = renderer_context['response']
        request = renderer_context['request']
        view = self.renderer_context['view']

        if response.status_code == status.HTTP_400_BAD_REQUEST:
            # Errors still need to display the list or detail information.
            # The only way we can get at that is to simulate a GET request.
            self.error_form = self.get_rendered_html_form(data, view, request.method, request)
            self.error_title = {'POST': 'Create', 'PUT': 'Edit'}.get(request.method, 'Errors')

            with override_method(view, request, 'GET') as request:
                response = view.get(request, *view.args, **view.kwargs)
            data = response.data

        template = loader.get_template(self.template)
        context = self.get_context(data, accepted_media_type, renderer_context)
        context = RequestContext(renderer_context['request'], context)
        ret = template.render(context)

        # Creation and deletion should use redirects in the admin style.
        if (response.status_code == status.HTTP_201_CREATED) and ('Location' in response):
            response.status_code = status.HTTP_302_FOUND
            response['Location'] = request.build_absolute_uri()
            ret = ''

        if response.status_code == status.HTTP_204_NO_CONTENT:
            response.status_code = status.HTTP_302_FOUND
            try:
                # Attempt to get the parent breadcrumb URL.
                response['Location'] = self.get_breadcrumbs(request)[-2][1]
            except KeyError:
                # Otherwise reload current URL to get a 'Not Found' page.
                response['Location'] = request.full_path
            ret = ''

        return ret
Exemplo n.º 19
0
    def _get_action_view(self, validated_data):
        request = self.context['request']
        path, resolver_match, url = validated_data['url']
        view = resolver_match.func

        # Make a fake request and use that for the view.
        method = self._ACTION_METHODS[validated_data['action']]
        with override_method(view, request, method) as new_request:
            new_request.resolver_match = resolver_match
            new_request.path = path
            new_request._data = new_request._full_data = validated_data.get('value', {})

            # `view` is actually a callback function (see View.as_view)
            # We replace it with our own callback instead,
            # just so we can override initialize_request below
            view_instance = view.view_class(**view.view_initkwargs)
            if hasattr(view_instance, 'get') and not hasattr(view_instance, 'head'):
                view_instance.head = view_instance.get
            view_instance.request = new_request
            view_instance.args = resolver_match.args
            view_instance.kwargs = resolver_match.kwargs

            # DRF's initialize_request() expects a WSGIRequest,
            # and wraps it with a *new* DRF Request object.
            # Instead, we want to keep the existing DRF Request object.
            def _initialize_request(request, *args, **kwargs):
                return request
            view_instance.initialize_request = _initialize_request

            def view_callback():
                return view_instance.dispatch(
                    view.request,
                    *view_instance.args,
                    **view_instance.kwargs
                )

            view_callback.view_instance = view_instance
            yield view_callback
    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)
        """
        # See issue #2089 for refactoring this.
        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:
            # If we're not using content overloading there's no point in
            # supplying a generic form, as the view won't treat the form's
            # value as the content of the request.
            if not (api_settings.FORM_CONTENT_OVERRIDE
                    and api_settings.FORM_CONTENTTYPE_OVERRIDE):
                return None

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

            # If possible, serialize the initial content for the generic form
            default_parser = view.parser_classes[0]
            renderer_class = getattr(default_parser, 'renderer_class', None)
            if (hasattr(view, 'get_serializer') and renderer_class):
                # View has a serializer defined and parser class has a
                # corresponding renderer that can be used to render the data.

                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance)
                else:
                    serializer = view.get_serializer()

                # Render the raw data content
                renderer = renderer_class()
                accepted = self.accepted_media_type
                context = self.renderer_context.copy()
                context['indent'] = 4
                content = renderer.render(serializer.data, accepted, context)
            else:
                content = None

            # Generate a generic form that includes a content type field,
            # and a content field.
            content_type_field = api_settings.FORM_CONTENTTYPE_OVERRIDE
            content_field = api_settings.FORM_CONTENT_OVERRIDE

            media_types = [parser.media_type for parser in view.parser_classes]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            # NB. http://jacobian.org/writing/dynamic-form-generation/
            class GenericContentForm(forms.Form):
                def __init__(self):
                    super(GenericContentForm, self).__init__()

                    self.fields[content_type_field] = forms.ChoiceField(
                        label='Media type', choices=choices, initial=initial)
                    self.fields[content_field] = forms.CharField(
                        label='Content',
                        widget=forms.Textarea,
                        initial=content)

            return GenericContentForm()
Exemplo n.º 21
0
    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)
        """
        # See issue #2089 for refactoring this.
        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

            # If possible, serialize the initial content for the generic form
            default_parser = view.parser_classes[0]
            renderer_class = getattr(default_parser, "renderer_class", None)
            if hasattr(view, "get_serializer") and renderer_class:
                # View has a serializer defined and parser class has a
                # corresponding renderer that can be used to render the data.

                if method in ("PUT", "PATCH"):
                    serializer = view.get_serializer(instance=instance)
                else:
                    serializer = view.get_serializer()

                # Render the raw data content
                renderer = renderer_class()
                accepted = self.accepted_media_type
                context = self.renderer_context.copy()
                context["indent"] = 4

                # strip HiddenField from output
                data = serializer.data.copy()
                for name, field in serializer.fields.items():
                    if isinstance(field, serializers.HiddenField):
                        data.pop(name, None)
                content = renderer.render(data, accepted, context)
                # Renders returns bytes, but CharField expects a str.
                content = content.decode()
            else:
                content = None

            # 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]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            class GenericContentForm(forms.Form):
                _content_type = forms.ChoiceField(
                    label="Media type",
                    choices=choices,
                    initial=initial,
                    widget=forms.Select(
                        attrs={"data-override": "content-type"}),
                )
                _content = forms.CharField(
                    label="Content",
                    widget=forms.Textarea(attrs={"data-override": "content"}),
                    initial=content,
                    required=False,
                )

            return GenericContentForm()
Exemplo n.º 22
0
    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        # See issue #2089 for refactoring this.
        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

        # If this is valid serializer data, and the form is for the same
        # HTTP method as was used in the request then use the existing
        # serializer instance, rather than dynamically creating a new one.
        if request.method == method and serializer is not None:
            try:
                kwargs = {"data": request.data}
            except ParseError:
                kwargs = {}
            existing_serializer = serializer
        else:
            kwargs = {}
            existing_serializer = None

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

            if method in ("DELETE", "OPTIONS"):
                return True  # Don't actually need to return a form

            has_serializer = getattr(view, "get_serializer", None)
            has_serializer_class = getattr(view, "serializer_class", None)

            if (not has_serializer and not has_serializer_class) or not any(
                    is_form_media_type(parser.media_type)
                    for parser in view.parser_classes):
                return

            if existing_serializer is not None:
                try:
                    return self.render_form_for_serializer(existing_serializer)
                except TypeError:
                    pass

            if has_serializer:
                if method in ("PUT", "PATCH"):
                    serializer = view.get_serializer(instance=instance,
                                                     **kwargs)
                else:
                    serializer = view.get_serializer(**kwargs)
            else:
                # at this point we must have a serializer_class
                if method in ("PUT", "PATCH"):
                    serializer = self._get_serializer(view.serializer_class,
                                                      view,
                                                      request,
                                                      instance=instance,
                                                      **kwargs)
                else:
                    serializer = self._get_serializer(view.serializer_class,
                                                      view, request, **kwargs)

            return self.render_form_for_serializer(serializer)
Exemplo n.º 23
0
    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)
        """
        # See issue #2089 for refactoring this.
        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

            # If possible, serialize the initial content for the generic form
            default_parser = view.parser_classes[0]
            renderer_class = getattr(default_parser, 'renderer_class', None)
            if (hasattr(view, 'get_serializer') and renderer_class):
                # View has a serializer defined and parser class has a
                # corresponding renderer that can be used to render the data.

                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance)
                else:
                    serializer = view.get_serializer()

                # Render the raw data content
                renderer = renderer_class()
                accepted = self.accepted_media_type
                context = self.renderer_context.copy()
                context['indent'] = 4
                content = renderer.render(serializer.data, accepted, context)
            else:
                content = None

            # 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]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            class GenericContentForm(forms.Form):
                _content_type = forms.ChoiceField(
                    label='Media type',
                    choices=choices,
                    initial=initial,
                    widget=forms.Select(attrs={'data-override': 'content-type'})
                )
                _content = forms.CharField(
                    label='Content',
                    widget=forms.Textarea(attrs={'data-override': 'content'}),
                    initial=content
                )

            return GenericContentForm()
Exemplo n.º 24
0
    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        # See issue #2089 for refactoring this.
        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

        # If this is valid serializer data, and the form is for the same
        # HTTP method as was used in the request then use the existing
        # serializer instance, rather than dynamically creating a new one.
        if request.method == method and serializer is not None:
            try:
                kwargs = {'data': request.data}
            except ParseError:
                kwargs = {}
            existing_serializer = serializer
        else:
            kwargs = {}
            existing_serializer = None

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

            if method in ('DELETE', 'OPTIONS'):
                return True  # Don't actually need to return a form

            has_serializer = getattr(view, 'get_serializer', None)
            has_serializer_class = getattr(view, 'serializer_class', None)

            if (
                (not has_serializer and not has_serializer_class) or
                not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)
            ):
                return

            if existing_serializer is not None:
                serializer = existing_serializer
            else:
                if has_serializer:
                    if method in ('PUT', 'PATCH'):
                        serializer = view.get_serializer(instance=instance, **kwargs)
                    else:
                        serializer = view.get_serializer(**kwargs)
                else:
                    # at this point we must have a serializer_class
                    if method in ('PUT', 'PATCH'):
                        serializer = self._get_serializer(view.serializer_class, view,
                                                          request, instance=instance, **kwargs)
                    else:
                        serializer = self._get_serializer(view.serializer_class, view,
                                                          request, **kwargs)

            if hasattr(serializer, 'initial_data'):
                serializer.is_valid()

            form_renderer = self.form_renderer_class()
            return form_renderer.render(
                serializer.data,
                self.accepted_media_type,
                {'style': {'template_pack': 'rest_framework/horizontal'}}
            )
Exemplo n.º 25
0
    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)
        """
        # See issue #2089 for refactoring this.
        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:
            # If we're not using content overloading there's no point in
            # supplying a generic form, as the view won't treat the form's
            # value as the content of the request.
            if not (api_settings.FORM_CONTENT_OVERRIDE and
                    api_settings.FORM_CONTENTTYPE_OVERRIDE):
                return None

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

            # If possible, serialize the initial content for the generic form
            default_parser = view.parser_classes[0]
            renderer_class = getattr(default_parser, 'renderer_class', None)
            if (hasattr(view, 'get_serializer') and renderer_class):
                # View has a serializer defined and parser class has a
                # corresponding renderer that can be used to render the data.

                if method in ('PUT', 'PATCH'):
                    serializer = view.get_serializer(instance=instance)
                else:
                    serializer = view.get_serializer()

                # Render the raw data content
                renderer = renderer_class()
                accepted = self.accepted_media_type
                context = self.renderer_context.copy()
                context['indent'] = 4
                content = renderer.render(serializer.data, accepted, context)
            else:
                content = None

            # Generate a generic form that includes a content type field,
            # and a content field.
            content_type_field = api_settings.FORM_CONTENTTYPE_OVERRIDE
            content_field = api_settings.FORM_CONTENT_OVERRIDE

            media_types = [parser.media_type for parser in view.parser_classes]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            # NB. http://jacobian.org/writing/dynamic-form-generation/
            class GenericContentForm(forms.Form):
                def __init__(self):
                    super(GenericContentForm, self).__init__()

                    self.fields[content_type_field] = forms.ChoiceField(
                        label='Media type',
                        choices=choices,
                        initial=initial
                    )
                    self.fields[content_field] = forms.CharField(
                        label='Content',
                        widget=forms.Textarea,
                        initial=content
                    )

            return GenericContentForm()
Exemplo n.º 26
0
    def get_raw_data_form(self, 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)
        """
        with override_method(view, request, method) as request:
            # If we're not using content overloading there's no point in
            # supplying a generic form, as the view won't treat the form's
            # value as the content of the request.
            if not (api_settings.FORM_CONTENT_OVERRIDE and api_settings.FORM_CONTENTTYPE_OVERRIDE):
                return None

            # Check permissions
            obj = getattr(view, "object", None)
            if not self.show_form_for_method(view, method, request, obj):
                return

            # If possible, serialize the initial content for the generic form
            default_parser = view.parser_classes[0]
            renderer_class = getattr(default_parser, "renderer_class", None)
            if hasattr(view, "get_serializer") and renderer_class:
                # View has a serializer defined and parser class has a
                # corresponding renderer that can be used to render the data.

                # Get a read-only version of the serializer
                serializer = view.get_serializer(instance=obj)
                if obj is None:
                    for name, field in serializer.fields.items():
                        if getattr(field, "read_only", None):
                            del serializer.fields[name]

                # Render the raw data content
                renderer = renderer_class()
                accepted = self.accepted_media_type
                context = self.renderer_context.copy()
                context["indent"] = 4
                content = renderer.render(serializer.data, accepted, context)
            else:
                content = None

            # Generate a generic form that includes a content type field,
            # and a content field.
            content_type_field = api_settings.FORM_CONTENTTYPE_OVERRIDE
            content_field = api_settings.FORM_CONTENT_OVERRIDE

            media_types = [parser.media_type for parser in view.parser_classes]
            choices = [(media_type, media_type) for media_type in media_types]
            initial = media_types[0]

            # NB. http://jacobian.org/writing/dynamic-form-generation/
            class GenericContentForm(forms.Form):
                def __init__(self):
                    super(GenericContentForm, self).__init__()

                    self.fields[content_type_field] = forms.ChoiceField(
                        label="Media type", choices=choices, initial=initial
                    )
                    self.fields[content_field] = forms.CharField(
                        label="Content", widget=forms.Textarea, initial=content
                    )

            return GenericContentForm()
Exemplo n.º 27
0
    def get_rendered_html_form(self, data, view, method, request):
        """
        Return a string representing a rendered HTML form, possibly bound to
        either the input or output data.

        In the absence of the View having an associated form then return None.
        """
        # See issue #2089 for refactoring this.
        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

        # If this is valid serializer data, and the form is for the same
        # HTTP method as was used in the request then use the existing
        # serializer instance, rather than dynamically creating a new one.
        if request.method == method and serializer is not None:
            try:
                kwargs = {"data": request.data}
            except ParseError:
                kwargs = {}
            existing_serializer = serializer
        else:
            kwargs = {}
            existing_serializer = None

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

            if method in ("DELETE", "OPTIONS"):
                return True  # Don't actually need to return a form

            has_serializer = getattr(view, "get_serializer", None)
            has_serializer_class = getattr(view, "serializer_class", None)

            if (not has_serializer and not has_serializer_class) or not any(
                is_form_media_type(parser.media_type) for parser in view.parser_classes
            ):
                return

            if existing_serializer is not None:
                serializer = existing_serializer
            else:
                if has_serializer:
                    if method in ("PUT", "PATCH"):
                        serializer = view.get_serializer(instance=instance, **kwargs)
                    else:
                        serializer = view.get_serializer(**kwargs)
                else:
                    # at this point we must have a serializer_class
                    if method in ("PUT", "PATCH"):
                        serializer = self._get_serializer(
                            view.serializer_class, view, request, instance=instance, **kwargs
                        )
                    else:
                        serializer = self._get_serializer(view.serializer_class, view, request, **kwargs)

            if hasattr(serializer, "initial_data"):
                serializer.is_valid()

            form_renderer = self.form_renderer_class()
            return form_renderer.render(
                serializer.data,
                self.accepted_media_type,
                dict(list(self.renderer_context.items()) + [("template", "rest_framework/api_form.html")]),
            )