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)
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()
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)
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')] ) )
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')]))
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)
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')
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)
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)
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)
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
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)
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()
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()
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
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
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()
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()
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)
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()
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'}} )
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_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()
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")]), )