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()
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')] ) )