2010-02-19 22 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/