Some checks failed
StarFields Django Rest Framework Generics / build (push) Failing after 12s
74 lines
3.0 KiB
Python
74 lines
3.0 KiB
Python
from rest_framework.parsers import BaseParser, DataAndFiles
|
|
from django.http.multipartparser import MultiPartParserError
|
|
from rest_framework.exceptions import ParseError
|
|
from django.http.multipartparser import \
|
|
MultiPartParser as DjangoMultiPartParser
|
|
from django.conf import settings
|
|
import json
|
|
|
|
|
|
class NestedJsonMultiPartParser(BaseParser):
|
|
"""
|
|
Parser for multipart form data, which may include file data.
|
|
"""
|
|
media_type = 'multipart/form-data'
|
|
|
|
def parse(self, stream, media_type=None, parser_context=None):
|
|
"""
|
|
Parses the incoming bytestream as a multipart encoded form,
|
|
and returns a DataAndFiles object.
|
|
The main difference with the parser from rest_framework.parsers
|
|
is that it attempts to parse nested strings as json to fit with
|
|
better with json payloads. I also ensure that a single file is
|
|
passed per field instead of a list which was erroring out
|
|
FieldFile.to_internal_value.
|
|
|
|
`.data` will be a dict containing all the form parameters.
|
|
`.files` will be a dict containing all the form files.
|
|
"""
|
|
parser_context = parser_context or {}
|
|
request = parser_context['request']
|
|
encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET)
|
|
meta = request.META.copy()
|
|
meta['CONTENT_TYPE'] = media_type
|
|
upload_handlers = request.upload_handlers
|
|
|
|
try:
|
|
parser = DjangoMultiPartParser(meta,
|
|
stream,
|
|
upload_handlers,
|
|
encoding)
|
|
data, files = parser.parse()
|
|
|
|
# Attempt to parse the multipart fields as json, this is not
|
|
# demanding since multiparts exist exclusively for file uploads
|
|
# which is much more demanding
|
|
data_dict = {}
|
|
for key in data.keys():
|
|
values = data[key]
|
|
try:
|
|
data_dict[key] = json.loads(values)
|
|
except Exception as e:
|
|
data_dict[key] = values
|
|
|
|
# Make sure the filenames become file names
|
|
for filename in files.keys():
|
|
uploaded_file = files[filename]
|
|
hasfilename = hasattr(uploaded_file, '_name')
|
|
hasname = hasattr(uploaded_file, 'name')
|
|
if hasfilename and not hasname:
|
|
uploaded_file.name = uploaded_file._name
|
|
|
|
# Turn the monstrous MultiValueDict into a normal dict so that
|
|
# there is only a single uploaded file per field passed
|
|
files_dict = {}
|
|
for key in files.keys():
|
|
uploaded_file = files[key]
|
|
if isinstance(uploaded_file, list):
|
|
uploaded_file = uploaded_file[0]
|
|
files_dict[key] = uploaded_file
|
|
|
|
return DataAndFiles(data_dict, files_dict)
|
|
except MultiPartParserError as exc:
|
|
raise ParseError('Multipart form parse error - %s' % str(exc))
|