【问题标题】:How to put a JSON file's content in a response如何将 JSON 文件的内容放入响应中
【发布时间】:2016-12-24 09:11:21
【问题描述】:

我的计算机上有一个文件,我正试图从 django 视图中将其作为 JSON 提供。

def serve(request):
    file = os.path.join(BASE_DIR, 'static', 'files', 'apple-app-site-association')
    response = HttpResponse(content=file)
    response['Content-Type'] = 'application/json'

当导航到 URL 时,我得到的是文件的路径

/Users/myself/Developer/us/www/static/files/apple-app-site-association

我在这里做错了什么?

【问题讨论】:

  • os.path.join 返回一个字符串(路径)。
  • @EmileBergeron 那么我如何获取文件的内容?我以为content=file 会这样做。
  • 你在变量file里面放了一个字符串,所以content=file把这个字符串作为响应的内容。搜索如何用python读取文件。
  • static是你的静态存储目录吗?
  • 如果你只是尝试提供一个文件目录,那么使用 python 有一个非常简单的方法:转到你提供服务的目录并运行python -m SimpleHTTPServer <port>.. . 有很多限制,但如果你安装了 python,它实际上需要几秒钟。通过网络浏览器,您将能够导航和下载

标签: python json django file


【解决方案1】:

os.path.join 返回一个字符串,这就是为什么您会在响应内容中获得路径。您需要先读取该路径下的文件。

对于静态文件

如果文件是静态的并且在磁盘上,您可以使用网络服务器将其返回,并且完全避免使用 python 和 django。如果文件需要验证才能下载,您仍然可以使用 django 处理,并返回 X-Sendfile header(这取决于网络服务器)。

为网络服务器提供静态文件是一项工作,Nginx 和 Apache 在这方面非常擅长,而 Python 和 Django 则是处理应用程序逻辑的工具。

读取文件的最简单方法

def serve(request):
    path = os.path.join(BASE_DIR, 'static', 'files', 'apple-app-site-association')
    with open(path , 'r') as myfile:
        data=myfile.read()
    response = HttpResponse(content=data)
    response['Content-Type'] = 'application/json'

这是受到How do I read a text file into a string variable in Python的启发

对于更高级的解决方案

StreamingHttpResponse 上查看dhke's answer

其他信息

【讨论】:

  • 无需从内存中提供文件。文件对象是可迭代的,StreamingHttpResponse 负责其余的工作。
  • @dhke 如果文件是静态的并且在磁盘上,则根本不需要 python 和 django。只需在网络服务器中进行配置就足够了。但由于 OP 不知道如何读取文件,我只是提供了最简单的方法来实现这一点。
  • 然后 OP 将学习 ;-)。尽管如此,还是感谢您提醒我,一个简单的重定向可能就可以了。
  • @dhke 我添加了指向您答案的链接以获得更高级的解决方案。
【解决方案2】:

如果您将HttpResponse 提供给content 的字符串,则将其作为HTTP 正文告诉serve that string

content 应该是一个迭代器或一个字符串。如果它是一个迭代器,它应该返回字符串,这些字符串将连接在一起形成响应的内容。如果不是迭代器或字符串,访问时会转为字符串。

既然你好像在用你的静态存储目录,那你还不如用staticfiles来处理内容:

from django.contrib.staticfiles.storage import staticfiles_storage
from django.http.response import StreamingHttpResponse

file_path = os.path.join('files', 'apple-app-site-association')

response = StreamingHttpResponse(content=staticfiles_storage.open(file_path))
return response

正如@Emile Bergeron's answer 中所述,对于静态文件,这应该已经是矫枉过正了,因为无论如何这些都应该可以从外部访问。所以一个简单的重定向到static(file_path) 也应该可以解决问题(假设您的网络服务器配置正确)。

提供任意文件:

from django.contrib.staticfiles.storage import staticfiles_storage
from django.http.response import StreamingHttpResponse

file_path = ...

response = StreamingHttpResponse(content=open(file_path, 'rb'))
return response

请注意,从 Django 1.10 及更高版本开始,文件句柄将自动关闭。

另外,如果可以从您的网络服务器访问该文件,请考虑使用django-sendfile,这样文件的内容就根本不需要通过 Django。

【讨论】:

  • 为什么你推荐使用StreamingHttpResponse而不是HttpResponse
  • @qarthandso 取决于您的用例。如果您使用StreamingHttpResponse,文件将在写入客户端时从文件系统中逐块读取。根据我的经验,如果您使用 HttpResponse(例如 ETag 生成),您最终可能会在内存中使用该文件。对于小文件:不要打扰。
  • @qarthandso 有了这个答案和我的答案,您拥有解决手头问题所需的一切。您应该考虑投票并接受一个以将问题标记为已回答。
猜你喜欢
  • 2017-03-01
  • 2021-08-30
  • 1970-01-01
  • 2016-04-23
  • 1970-01-01
  • 2020-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多