Created
February 12, 2026 14:09
-
-
Save federicoemartinez/4fb5b033684802e0bc9a73e53ab1897f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import io | |
| from django.conf import settings | |
| from django.core.files.uploadedfile import InMemoryUploadedFile | |
| from django.http import QueryDict | |
| from rest_framework.exceptions import ParseError | |
| from rest_framework.parsers import BaseParser | |
| class DefnullPushMultipartParser(BaseParser): | |
| """ | |
| High-performance multipart parser using defnull/multipart's PushMultipartParser. | |
| This is the FASTEST parser in our benchmarks - approximately 2x faster than | |
| DRF's default MultiPartParser. It works in both sync and async Django views. | |
| The PushMultipartParser is a streaming, non-blocking parser that processes | |
| data incrementally without buffering the entire request in memory. | |
| Install: pip install multipart | |
| Usage: | |
| from parsers import DefnullPushMultipartParser | |
| class MyUploadView(APIView): | |
| parser_classes = [DefnullPushMultipartParser] | |
| def post(self, request): | |
| data = request.data['data'] | |
| files = request.data['files'] | |
| # ... | |
| """ | |
| media_type = 'multipart/form-data' | |
| def parse(self, stream, media_type=None, parser_context=None): | |
| import multipart as defnull_multipart | |
| request = parser_context.get('request') | |
| encoding = parser_context.get('encoding', settings.DEFAULT_CHARSET) | |
| content_type = request.content_type | |
| # Parse options header to get boundary | |
| _, options = defnull_multipart.parse_options_header(content_type) | |
| boundary = options.get('boundary') | |
| if not boundary: | |
| raise ParseError('Missing boundary in multipart content-type header') | |
| fields = QueryDict(mutable=True) | |
| from django.utils.datastructures import MultiValueDict | |
| files_dict = MultiValueDict() | |
| current_segment = None | |
| current_data = [] | |
| with defnull_multipart.PushMultipartParser(boundary, header_charset=encoding) as parser: | |
| # Use blocking parse for sync context | |
| for event in parser.parse_blocking(stream.read): | |
| if isinstance(event, defnull_multipart.MultipartSegment): | |
| # New part started | |
| if current_segment is not None: | |
| # Finalize previous part | |
| self._finalize_part( | |
| current_segment, current_data, | |
| fields, files_dict, encoding | |
| ) | |
| current_segment = event | |
| current_data = [] | |
| elif event: # bytes data | |
| current_data.append(event) | |
| else: # None = end of part | |
| if current_segment is not None: | |
| self._finalize_part( | |
| current_segment, current_data, | |
| fields, files_dict, encoding | |
| ) | |
| current_segment = None | |
| current_data = [] | |
| return {'data': fields, 'files': files_dict} | |
| def _finalize_part(self, segment, data_chunks, fields, files_dict, encoding): | |
| """Finalize a multipart segment and add to fields or files.""" | |
| name = segment.name | |
| data = b''.join(data_chunks) | |
| if segment.filename: | |
| uploaded_file = InMemoryUploadedFile( | |
| file=io.BytesIO(data), | |
| field_name=name, | |
| name=segment.filename, | |
| content_type=segment.content_type or 'application/octet-stream', | |
| size=len(data), | |
| charset=encoding, | |
| ) | |
| files_dict.appendlist(name, uploaded_file) | |
| else: | |
| fields.appendlist(name, data.decode(encoding)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment