2010-02-19 23 views
10

我需要根据特定的逻辑返回css文件和js文件。显然,静态服务并不能满足我需要。我有一个视图,其渲染方法使用逻辑来查找正确的文件,但是我必须返回它。从技术上讲,我可以读取文件并将其填入具有适当MIME类型的HttpResponse对象,但我想知道是否有更好的策略。 (如fpassthru()在PHP)如何返回在django中通过视图的静态文件?

+1

哪一个不执行你所需要的,Web服务器静态文件服务,或者'django.views.static.serve'? – 2010-02-19 13:07:04

+0

两者都不是:) – 2010-02-19 15:22:25

+0

其实,语法问题。它是“不是”还是“两者”? – 2010-02-19 15:24:02

回答

-1

应该浪费使用Django提供静态内容(更不用提,几个数量级慢)。

我的观点,而转换为背景处理器,并使用变量模板查找块包含。

+0

这正是我想要移开的东西。我已经包括了这些东西,结果是CSS和js文件被硬编码到html文件中,阻止了任何形式的缓存(因为整个页面被认为会改变)。我希望能够发布js和css,但由于此次发货依赖于可用的应用程序插件,因此我需要在发送文件之前执行一些逻辑。 – 2010-02-19 07:14:10

+0

你的意思是阻止任何形式的Django缓存?因为将css&js包含在硬编码模板中不会阻止用户的浏览器缓存它们。我不清楚实际问题是什么。这听起来像是由于动态包含而导致无法缓存整个页面。为什么不缓存页面的其余部分,并让浏览器/你的Web服务器完成剩下的工作(这是它的工作)? – Tom 2010-02-20 14:52:32

+0

这将作出真正的答案后的一个很好的评论或警告。 – 2017-01-02 22:52:58

1

传递一个迭代(如open()的结果)到HttpResponse构造函数。

1

为什么不返回HttpResponseRedirect正确的静态文件的位置?

+2

,因为该文件不能直接访问。 – 2010-02-19 10:15:14

8

你在使用什么网络服务器软件?

至少Apache和Nginx的,有一个模块使您使用X-SendFile HTTP标头。 NginX网站上说Lighty也可以做到这一点。

在您的包装视图:

... 

abspath = '/most_secret_directory_on_the_whole_filesystem/protected_filename.css' 

response = HttpResponse() 
response['X-Sendfile'] = abspath 

response['Content-Type'] = 'mimetype/submimetype' 
# or let your webserver auto-inject such a header field 
# after auto-recognition of mimetype based on filename extension 

response['Content-Length'] = <filesize> 
# can probably be left out if you don't want to hassle with getting it off disk. 
# oh, and: 
# if the file is stored via a models.FileField, you just need myfilefield.size 

response['Content-Disposition'] = 'attachment; filename=%s.css' \ 
    % 'whatever_public_filename_you_need_it_to_be' 

return response 

然后你就可以通过http://mysite.com/url_path/to/serve_hidden_css_file/连接视图。

你可以使用它任何时候你需要做的在被请求的文件的东西,不应该是用户直接访问,例如限制谁可以访问它,或计数请求给它的统计数据,或什么的。

对于Apache:http://tn123.ath.cx/mod_xsendfile/
对于NGINX:http://wiki.nginx.org/NginxXSendfile

16

这是我用什么:

test_file = open('/home/poop/serve/test.pdf', 'rb') 
response = HttpResponse(content=test_file) 
response['Content-Type'] = 'application/pdf' 
response['Content-Disposition'] = 'attachment; filename="%s.pdf"' \ 
            % 'whatever' 
return response 
+0

我需要open()函数的'rb'模式,或者这个代码搞乱了我的pdf。这与django/views/static.py中使用的代码相匹配。 – 2012-05-14 14:20:52

+2

在我看来,这导致整个文件被加载到内存中。不是吗? – 2013-03-12 06:08:54

+0

@EmanuelePaolini:您可以将迭代器传递给'HttpResponse',我修改了答案以反映这一点。 – Flimm 2016-02-02 17:41:55

4

你为什么不使用Django staticfiles视图

from django.contrib.staticfiles.views import serve 

... 
def view_function(request): 
    return serve(request, 'absolute_path_to_file_name') 
+7

的[文档](https://docs.djangoproject.com/en/1.4/ref/contrib/staticfiles/#other-helpers)说: “警告 此视图将仅在DEBUG是让人爱不释手。 这是因为这种观点非常低效,可能并不安全,这只适用于本地开发,不应该用于生产。“ – 2013-02-12 12:47:54

1

内部服务直接来自视图的文件非常慢。如果您正在寻找正常文件服务,请参阅此问题:Having Django serve downloadable files

要通过视图非常容易地为文件提供服务(例如,用于调试目的)请继续阅读。

# In your urls.py: 
url(r'^test-files/(?P<name>.+)/$', views.test_files, name='test_files'), 

# In your views.py: 
from django.http.response import HttpResponse 
from django.views.decorators.csrf import csrf_exempt 

@csrf_exempt # (Allows file download with POST requests, can be omitted) 
def test_files(request, name): 
    if name == "myxml": 
     fsock = open("/djangopath/data/static/files/my.xml", "rb") 
     return HttpResponse(fsock) 

这可以让你从下载的文件:http://127.0.0.1:8080/app/test-files/myxml/