gpt4 book ai didi

python - 将 StreamingHttpResponse 与 Django Rest Framework CSV 一起使用

转载 作者:太空狗 更新时间:2023-10-29 20:29:51 33 4
gpt4 key购买 nike

我有一个标准的 DRF 网络应用程序,可以为其中一条路线输出 CSV 数据。呈现整个 CSV 表示需要一段时间才能完成。数据集非常大,所以我想要一个流式 HTTP 响应,这样客户端就不会超时。

但是使用 https://github.com/mjumbewu/django-rest-framework-csv/blob/2ff49cff4b81827f3f450fd7d56827c9671c5140/rest_framework_csv/renderers.py#L197 中提供的示例并没有完全做到这一点。数据仍然是一个很大的有效载荷,而不是被分 block ,客户端最终在接收到字节之前等待响应。

结构类似如下:

模型.py

class Report(models.Model):
count = models.PostiveIntegerField(blank=True)
...

渲染器.py

class ReportCSVRenderer(CSVStreamingRenderer):
header = ['count']

序列化器.py

class ReportSerializer(serializers.ModelSerializer):
count = fields.IntegerField()

class Meta:
model = Report

views.py

class ReportCSVView(generics.Viewset, mixins.ListModelMixin):
def get_queryset(self):
return Report.objects.all()

def list(self, request, *args, **kwargs):
queryset = self.get_queryset()
data = ReportSerializer(queryset, many=True)
renderer = ReportCSVRenderer()

response = StreamingHttpResponse(renderer.render(data), content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="f.csv"'

return response

注意:必须注释掉或更改一些内容。

谢谢

最佳答案

一个更简单的解决方案,灵感来自 @3066d0 的解决方案:

渲染器.py

class ReportsRenderer(CSVStreamingRenderer):
header = [ ... ]
labels = { ... }

views.py

class ReportCSVViewset(ListModelMixin, GenericViewSet):
queryset = Report.objects.select_related('stuff')
serializer_class = ReportCSVSerializer
renderer_classes = [ReportsRenderer]
PAGE_SIZE = 1000

def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
response = StreamingHttpResponse(
request.accepted_renderer.render(self._stream_serialized_data(queryset)),
status=200,
content_type="text/csv",
)
response["Content-Disposition"] = 'attachment; filename="reports.csv"'
return response

def _stream_serialized_data(self, queryset):
serializer = self.get_serializer_class()
paginator = Paginator(queryset, self.PAGE_SIZE)
for page in paginator.page_range:
yield from serializer(paginator.page(page).object_list, many=True).data

重点是您需要将生成序列化数据的生成器作为 data 参数传递给渲染器,然后 CSVStreamingRenderer 执行其操作并流式传输响应本身。我更喜欢这种方法,因为这样你就不需要覆盖第三方库的代码。

关于python - 将 StreamingHttpResponse 与 Django Rest Framework CSV 一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46694898/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com