1. 程式人生 > >Django中管理使用靜態檔案

Django中管理使用靜態檔案

Managing static files

Django developers mostly concern themselves with the dynamic parts of web applications – the views and templates that render a new for each request. But web applications have other parts: the static files (images, CSS, Javascript, etc.) that are needed to render a complete web page.

Django開發者大多關心web應用中動態頁面的開發,對每一個請求返回新檢視和模版。但是web應用還有另外一個部分:靜態檔案(圖片,樣式表,js指令碼等等)在一個完整的web頁面中也是需要的。

For small projects, this isn’t a big deal, because you can just keep the static files somewhere your web server can find it. However, in bigger projects – especially those comprised of multiple apps – dealing with the multiple sets of static files provided by each application starts to get tricky.

對於小型的工程來說,這並不難做到。因為你可以將這些靜態檔案放在web伺服器可以找到的位置。然而,對於大型工程,尤其是含有多個app的複雜工程,處理各個應用提供的一系列的靜態檔案將變得麻煩。

That’s what django.contrib.staticfiles is for: it collects static files from each of your applications (and any other places you specify) into a single location that can easily be served in production.

這正是django.contrib.staticfiles的目標:它從每個應用(或者你制定的路徑)中搜集靜態檔案,放到一個在專案中可以較容易被找到的位置中。

Note    註解

If you’ve used the django-staticfiles third-party app before, then django.contrib.staticfiles will look very familiar. That’s because they’re essentially the same code:django.contrib.staticfiles started its life asdjango-staticfiles and was merged into Django 1.3.

如果你曾使用過第三方的django-staticfiles應用,這與django.contrib.staticfiles看起來會很相似。這是因為他們本質上都是相同的程式碼:django.contrib.staticfiles由django-staticfiles開發展而來,並被合併到了Django1.3版本中。

If you’re upgrading from django-staticfiles, please seeUpgrading from django-staticfiles, below, for a few minor changes you’ll need to make.

1. Using django.contrib.staticfiles

1.1 Basic usage

1.2 Deploying static files in a nutshell

2. Referring to static files in templates

2.1 With a context processor

2.2 With a template tag

3. Serving static files in development

The static files tools are mostly designed to help with getting static files successfully deployed into production. This usually means a separate, dedicated static file server, which is a lot of overhead to mess with when developing locally. Thus, the staticfiles app ships with a quick and dirty helper view that you can use to serve files locally in development.

靜態檔案工具主要是為了使靜態檔案能夠成功部署到產品中而設計的。這通常意味著需要一個獨立的、專用的靜態檔案伺服器,當本地部署時這是一個很大的開銷。因此,staticfiles程式附帶一個快速和dirty(無法翻譯的詞,解釋不通)的輔助檢視,您可以在開發中使用它在本地伺服器提供檔案。

This view is automatically enabled and will serve your static files at STATIC_URL when you use the built-in runserver management command.

當使用內建的runserver管理命令時,這一檢視會自動被使用並且以STATIC_URL為路徑提供靜態檔案服務。

To enable this view if you are using some other server for local development, you’ll add a couple of lines to your URLconf. The first line goes at the top of the file, and the last line at the bottom:

為了使用這個檢視(如果你使用了一些其它的伺服器做本地部署)你需要在URLconf中新增幾行。第一行位於配置檔案的第一行,最後一行在檔案低端。

from django.contrib.staticfiles.urls import staticfiles_urlpatterns

# ... the rest of your URLconf goes here ...

urlpatterns += staticfiles_urlpatterns()

This will inspect your STATIC_URL setting and wire up the view to serve static files accordingly. Don’t forget to set the STATICFILES_DIRS setting appropriately to let django.contrib.staticfiles know where to look for files additionally to files in app directories.

這會檢查你STATIC_URL的設定並接通檢視服務提供靜態檔案。不要忘記設定適當的設定STATICFILES_DIRS項使django.contrib.staticfiles能夠知曉在app目錄的什麼位置去尋找要載入的檔案。

Warning

This will only work if DEBUG is True.這隻有在DEBUG為True時才有效。

That’s because this view is grossly inefficient and probably insecure. This is only intended for local development, and should never be used in production.

這是因為這個檢視效率很低而且不安全。這只是為本地部署設計的,絕不能用於產品。

Additionally, when using staticfiles_url patterns your STATIC_URL setting can’t be empty or a full URL, such as http://static.example.com/.

另外,當使用staticfiles_url時,STATIC_URL的配置不能為空或者一個整路徑。

For a few more details on how the staticfiles can be used during development, seeStatic file development view.

3.1 Serving other directories 為其它目錄服務

serve(request, path, document_root, show_indexes=False)

There may be files other than your project’s static assets that, for convenience, you’d like to have Django serve for you in local development. The serve() view can be used to serve any directory you give it. (Again, this view is not hardened for production use, and should be used only as a development aid; you should serve these files in production using a real front-end webserver).

The most likely example is user-uploaded content in MEDIA_ROOT. staticfiles is intended for static assets and has no built-in handling for user-uploaded files, but you can have Django serve your MEDIA_ROOT by appending something like this to your URLconf:

from django.conf import settings

# ... the rest of your URLconf goes here ...

if settings.DEBUG:
    urlpatterns += patterns('',
        url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {
            'document_root': settings.MEDIA_ROOT,
        }),
   )

Note, the snippet assumes your MEDIA_URL has a value of '/media/'. This will call the serve() view, passing in the path from the URLconf and the (required) document_root parameter.

static(prefix, view='django.views.static.serve', **kwargs)

Since it can become a bit cumbersome to define this URL pattern, Django ships with a small URL helper function static() that takes as parameters the prefix such as MEDIA_URL and a dotted path to a view, such as 'django.views.static.serve'. Any other function parameter will be transparently passed to the view.

An example for serving MEDIA_URL ('/media/') during development:
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = patterns('',
    # ... the rest of your URLconf goes here ...
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

Note

This helper function will only be operational in debug mode and if the given prefix is local (e.g. /static/) and not a URL (e.g. http://static.example.com/).

4. Serving static files in production

The basic outline of putting static files into production is simple: run the collectstatic command when static files change, then arrange for the collected static files directory (STATIC_ROOT) to be moved to the static file server and served.

Of course, as with all deployment tasks, the devil’s in the details. Every production setup will be a bit different, so you’ll need to adapt the basic outline to fit your needs. Below are a few common patterns that might help.

4.1 Serving the app and your static files from the same server

If you want to serve your static files from the same server that’s alreadyserving your site, the basic outline gets modified to look something like:

You’ll probably want to automate this process, especially if you’ve gotmultiple web servers. There’s any number of ways to do this automation, butone option that many Django developers enjoy isFabric.

Below, and in the following sections, we’ll show off a few example fabfiles(i.e. Fabric scripts) that automate these file deployment options. The syntaxof a fabfile is fairly straightforward but won’t be covered here; consultFabric’s documentation, for a complete explanation of the syntax..

So, a fabfile to deploy static files to a couple of web servers might looksomething like:

from fabric.api import *

# Hosts to deploy onto
env.hosts = ['www1.example.com', 'www2.example.com']

# Where your project code lives on the server
env.project_root = '/home/www/myproject'

def deploy_static():
    with cd(env.project_root):
        run('./manage.py collectstatic -v0 --noinput')

4.2 Serving static files from a dedicated server

Most larger Django apps use a separate Web server – i.e., one that’s not alsorunning Django – for serving static files. This server often runs a differenttype of web server – faster but less full-featured. Some good choices are:

Configuring these servers is out of scope of this document; check eachserver’s respective documentation for instructions.

Since your static file server won’t be running Django, you’ll need to modifythe deployment strategy to look something like:

  • When your static files change, run collectstatic locally.
  • Push your local STATIC_ROOT up to the static file serverinto the directory that’s being served.rsync is a goodchoice for this step since it only needs to transfer thebits of static files that have changed.

Here’s how this might look in a fabfile:

from fabric.api import *
from fabric.contrib import project

# Where the static files get collected locally
env.local_static_root = '/tmp/static'

# Where the static files should go remotely
env.remote_static_root = '/home/www/static.example.com'

@roles('static')
def deploy_static():
    local('./manage.py collectstatic')
    project.rsync_project(
        remote_dir = env.remote_static_root,
        local_dir = env.local_static_root,
        delete = True
    )


4.3 Serving static files from a cloud service or CDN

Another common tactic is to serve static files from a cloud storage providerlike Amazon’sS3 and/or a CDN (content delivery network). This lets youignore the problems of serving static files, and can often make forfaster-loading webpages (especially when using a CDN).

When using these services, the basic workflow would look a bit like the above,except that instead of usingrsync to transfer your static files to theserver you’d need to transfer the static files to the storage provider or CDN.

There’s any number of ways you might do this, but if the provider has an API acustom file storage backend will make theprocess incredibly simple. If you’ve written or are using a 3rd party customstorage backend, you can tell collectstatic to use it by settingSTATICFILES_STORAGE to the storage engine.

For example, if you’ve written an S3 storage backend inmyproject.storage.S3Storage you could use it with:

STATICFILES_STORAGE = 'myproject.storage.S3Storage'

Once that’s done, all you have to do is run collectstatic and yourstatic files would be pushed through your storage package up to S3. If youlater needed to switch to a different storage provider, it could be as simpleas changing your STATICFILES_STORAGE setting.

For details on how you’d write one of these backends,Writing a custom storage system.

See also

The django-storages project is a 3rd party app that provides manystorage backends for many common file storage APIs (includingS3).


5. Upgrading from django-staticfiles

6. Learn more