django:如何将传入的 POST 数据作为类文件对象用于流处理

django: how to consume incoming POST data as a file-like obj for streaming processing

我正在使用 python + Django 来处理传入的 Web 请求,这些请求可以 post 大量 JSON 作为 POST 数据字段之一附加(例如 var1=abc&json_var=lots_of_data&other_var=xxx)。我想使用我自己的流式处理 json 解析器以流式处理方式处理 JSON,该解析器采用类似文件的句柄作为其输入参数。从 https://docs.djangoproject.com/en/1.11/ref/request-response/ 看来这是可行的,使用 HttpRequest.__iter__(),但我找不到任何示例说明如何使用我自己的代码实现此目的(即不只是导入像 xml.etree.ElementTree 这样的库).

基本上,我想执行以下操作:

POST 请求 w/ big JSON => Django/python => 创建类似文件的句柄来读取 POST => 流 url 解码器 = > 流媒体 JSON 处理器

我可以将 ijson 用于流式处理 JSON 处理器。如何填补创建 POST 数据的类文件句柄并将其传递给流式 url 解码器的两个空白?我不想自己动手,但我想如果有必要我可以。

__iter__() 只是 xreadlines 的包装器,而 xreadlines 只是一个循环,它使用 HttpRequest 的输入流一次调用并生成一行数据。所以你可以用这样的时间替换手册中的示例代码

parser = MyJsonParser()
for line in (request):
    parser.process(line)

您尚未 post 编写代码,因此您必须根据需要进行调整。

另请注意,这可能是也可能不是真正的流式传输过程,具体取决于您的设置。您的服务器机制很可能会立即读取整个 post 正文并将其传递给您的视图,而不是一次发送一行。在这种情况下,流式传输的外观是虚幻的。

我只能通过滚动我自己的生成器和迭代器来解决这个问题。解决这个问题有几个关键:

  • 寻找如何在分块发送数据的情况下访问 POST 数据的类文件句柄。我能够在 request.META.get('wsgi.input') 找到它,我通过使用 this post 转储所有请求属性
  • 找到了它
  • 使用我自己的生成器来读取类似文件的句柄并生成 (varname, data_chunk) 对
  • 基于 this post 的修改版本,推出我自己的生成器,以创建具有正常 read() 操作但具有三个附加功能的类文件句柄:
    • f.varname returns 当前正在读取的变量名
    • 数据在从 read() 传回之前是 url-未编码的
    • f.next_pair() 推进句柄读取下一个变量。因此,调用 f.read() 直到完成第一个变量,然后如果还有另一个变量,f.next_pair() 将 return 为真,而 f.read() 可以再次调用直到完成读取下一个变量
  • 可以在主循环中实现进一步的流处理

将它们放在一起看起来像:

f = request.META.get('wsgi.input')
ff = some_magic_adaptor(qs_from_file_to_generator(f))

while ff.next_pair():
    print 'varname:' + ff.varname
    if ff.varname == 'stream_parse_this':
        parser = stream_parser(ff)
        for event_results in parser:
            do_something

    while True:
        data = ff.read(buffer_size)
        if not data:
            break
        do_something_with_data_chunk(data)