Ejemplo n.º 1
0
def _query_results_to_csv(
        query_results: DocumentQueryResults) -> StreamingHttpResponse:
    resp = StreamingHttpResponse(csv_gen(query_results.column_codes,
                                         query_results.fetch(),
                                         query_results.column_titles),
                                 content_type='text/csv')
    resp['Content-Disposition'] = 'attachment; filename="export.csv"'
    return resp
Ejemplo n.º 2
0
    def get(self, request, document_type_code: str, *_args, **_kwargs):
        start = time.time()
        try:
            document_type = DocumentType.objects.get(code=document_type_code)

            project_ids = as_int_list(request.GET,
                                      'project_ids')  # type: List[int]

            columns = as_str_list(request.GET, 'columns')

            fmt = request.GET.get('fmt') or self.FMT_JSON

            offset = as_int(request.GET, 'offset', None)
            if offset is not None and offset < 0:
                offset = None

            limit = as_int(request.GET, 'limit', None)
            if limit is not None and limit <= 0:
                limit = None

            # For json output we limit number of returned documents because we dont use streaming response for JSON
            # and want to keep it fast.
            if fmt == self.FMT_JSON and (
                    limit is None or limit > self.MAX_RETURNED_DOCUMENTS_JSON):
                limit = self.MAX_RETURNED_DOCUMENTS_JSON

            saved_filters = as_int_list(request.GET,
                                        'saved_filters')  # type: List[int]

            column_filters = list()
            for param, value in request.GET.items():  # type: str, str
                if param.startswith(self.URL_PARAM_PREFIX_FILTER):
                    column_filters.append(
                        (param[len(self.URL_PARAM_PREFIX_FILTER):], value))

            order_by = request.GET.get('order_by') or None  # type: str
            order_by = parse_order_by(order_by) if order_by else None

            save_filter = as_bool(request.GET, 'save_filter',
                                  False)  # type: bool

            return_reviewed = as_bool(request.GET, 'return_reviewed', False)
            return_total = as_bool(request.GET, 'return_total', True)
            return_data = as_bool(request.GET, 'return_data', True)
            ignore_errors = as_bool(request.GET, 'ignore_errors', True)

            if project_ids and save_filter:
                column_filters_dict = {c: f for c, f in column_filters}
                for project_id in project_ids:
                    SavedFilter.objects.update_or_create(
                        user=request.user,
                        document_type=document_type,
                        filter_type=FT_USER_DOC_GRID_CONFIG,
                        project_id=project_id,
                        defaults={
                            'user':
                            request.user,
                            'document_type':
                            document_type,
                            'filter_type':
                            FT_USER_DOC_GRID_CONFIG,
                            'project_id':
                            project_id,
                            'columns':
                            columns,
                            'column_filters':
                            column_filters_dict,
                            'title':
                            None,
                            'order_by': [(column, direction.value)
                                         for column, direction in order_by]
                            if order_by else None
                        })
            query_results = get_documents(
                requester=request.user,
                document_type=document_type,
                project_ids=project_ids,
                column_names=columns,
                saved_filter_ids=saved_filters,
                column_filters=column_filters,
                order_by=order_by,
                offset=offset,
                limit=limit,
                return_documents=return_data,
                return_reviewed_count=return_reviewed,
                return_total_count=return_total,
                ignore_errors=ignore_errors)  # type: DocumentQueryResults

            if fmt.lower() == 'csv':
                if not return_data:
                    raise APIRequestError(
                        'Export to csv requested with return_data=false')
                else:
                    resp = StreamingHttpResponse(csv_gen(
                        query_results.column_codes, query_results.fetch(),
                        query_results.column_titles),
                                                 content_type='text/csv')
                    resp[
                        'Content-Disposition'] = 'attachment; filename="export.csv"'
                    return resp
            else:
                if query_results is None:
                    return Response({'time': time.time() - start})

                # As we limit the number of returned documents for JSON we can keep response in non-streaming form.
                return Response(
                    _query_results_to_json(query_results,
                                           time.time() - start))

                # Switch to StreamingHttpResponse if/when we really need to return very big json output.
                # _query_results_to_json() returns dict with document items backed with a generator.
                # But on local tests for small number of documents the streaming json output works two times
                # slower than non-streaming response. CSV works the same fast.
                # return StreamingHttpResponse(json_gen(_query_results_to_json(query_results, time.time() - start)),
                #       content_type='application/json')
        except APIRequestError as e:
            return e.to_response()
        except Exception as e:
            return APIRequestError(message='Unable to process request',
                                   caused_by=e,
                                   http_status_code=500).to_response()