0

I am trying to stream several large json files to the front end at a time (I need to stream all of them one by one, and can't split it into several requests):

def stream_response_generator(response):
    yield json.dumps({ 'searchedVariants': response['searchedVariants']})
    yield json.dumps({ 'genesById': response['genesById']})
    yield json.dumps({ 'locusListsByGuid': response['locusListsByGuid']})
    yield json.dumps({ 'genesQcData': response['genesQcData']})

@login_required(login_url=API_LOGIN_REQUIRED_URL)
@csrf_exempt
@log_request(name='query_variants_handler')
def query_variants_handler(request, search_hash):
    ...
    return StreamingHttpResponse(stream_response_generator(response), content_type='application/octet-stream')

Only the very first searchedVariants response is streaming to the front end but other 3 are omitted. I verified it printing out the response on the frontend:

fetch(url, {
    method: 'POST',
    credentials: 'include',
    body: JSON.stringify(search),
    signal: signal,
}).then((response) => {
  const reader = response.body.getReader()
  let decoder = new TextDecoder('utf8');
  let read
  reader.read().then(read = (result) => {
    if (result.done) return
    let chunk = decoder.decode(result.value);
    console.log(chunk)

    reader.read().then(read)
  })  
})  

In some tutorials, e.g.

https://andrewbrookins.com/django/how-does-djangos-streaminghttpresponse-work-exactly/

Its written that we should pass a function generator instead of calling a function like I do, however, when I do that:

def stream_response_generator(response):
    def generator():
        yield json.dumps({ 'searchedVariants': response['searchedVariants']})
        yield json.dumps({ 'genesById': response['genesById']})
        yield json.dumps({ 'locusListsByGuid': response['locusListsByGuid']})
        yield json.dumps({ 'genesQcData': response['genesQcData']})

return generator

@login_required(login_url=API_LOGIN_REQUIRED_URL)
@csrf_exempt
@log_request(name='query_variants_handler')
def query_variants_handler(request, search_hash):
    ...
    return StreamingHttpResponse(stream_response_generator(response), content_type='application/octet-stream')

I am getting an error:

2022-10-21 03:34:28,165 ERROR:  Traceback (most recent call last):
  File "/site-packages/django/core/handlers/base.py", line 179, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/python3.6/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/gris/decorators.py", line 26, in wrapper
    return f(request, *args, **kwargs)
  File "/variant_search_api.py", line 141, in query_variants_handler
    return StreamingHttpResponse(stream_response_generator(response), content_type='application/octet-stream')
  File "/python3.6/site-packages/django/http/response.py", line 367, in __init__
    self.streaming_content = streaming_content
  File "/python3.6/site-packages/django/http/response.py", line 382, in streaming_content
    self._set_streaming_content(value)
  File "/python3.6/site-packages/django/http/response.py", line 386, in _set_streaming_content
    self._iterator = iter(value)
TypeError: 'function' object is not iterable

I suspect it is somehow related to @csrf_exempt decorator but not sure. So, why does StreamingHttpResponse not stream other values? How to fix it?

Nikita Vlasenko
  • 4,004
  • 7
  • 47
  • 87

0 Answers0