英文原文:[http://agiliq.com/blog/2013/03/serving-static-files-in-django/]

译文:[http://segmentfault.com/a/1190000000358284]

处理静态文件,尤其是在开发时,是一件蛋疼的事情。在这篇文章中,我们将会讨论一些设置,目录结构和他们之间的相互影响。设置好DEBUG = True然后我们开始开发吧。

我们将会创建一个Django项目,这样可以让我们更好的了解我们讨论的这些这些文件在什么目录中。我们将会使用Django1.4,这些都也能在Django1.3中工作,因为没有在Django1.2下进行测试,所以对1.2版本下是否有问题不是很清楚。

创建项目

如果你不需要这部分,可以直接跳到处理静态文件这一节。只要保证你看过了这节底部的目录结构并对其有了解,这样你阅读后面的内容会更舒服。

我们将在命名为staticvirt的虚拟环境中做所有事情,所以我们需要命令

~$ virtualenv staticvirt

接下来我们需要在这个虚拟环境中创建一个Django项目。确保你进入了虚拟环境的目录,并且激活了该环境。同时也要保证在这个虚拟环境中安装了Django,因为我们不想污染系统的包环境。

~$ cd staticvirt/
~/staticvirt$ source bin/activate
(staticvirt)~/staticvirt$ pip install django==1.4

创建一个Django项目。

django-admin.py startproject test_project

进入项目所在系统。

cd test_project/

让我们看看现在的目录结构。

(staticvirt)~/staticvirt/test_project$ tree
.
|-- manage.py
*-- test_project
|-- __init__.py
|-- settings.py
|-- urls.py
*-- wsgi.py
1 directory, 5 files

现在查看下test_project/settings.py的内容。搜索所有包括static的行,下面我列出所有包括static的行。

STATIC_ROOT = ''   

STATIC_URL = '/static/'  

STATICFILES_DIRS = ()  

STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'django.contrib.staticfiles.finders.DefaultStorageFinder',
) INSTALLED_APPS = (
....
....
'django.contrib.staticfiles',
....
)

然而,这里所看到的都是Django提供的默认设置,我们没有做任何的设置。

我们创建一个app,我们将会在里面创建一个template,然后会写一些静态文件,比如样式文件,然后在模板中使用这个样式文件。

python manage.py startapp some_app

some_app添加进test_project/settings.py中的INSTALLED_APPS

我们需要一个urls.py文件来为some_app定制路由。项目的urls.py应该包括some_app中的urls.py。所以,我们在test_project/urls.py中添加以下一行。

url(r'^some_app/', include('some_app.urls'))

some_app的urls.py文件中添加以下内容。

url(r'^home$', direct_to_template, {"template": "some_app/home.html"})

创建一个名为templates的目录,然后将其添加进TEMPLATE_DIRS。我在manage.py同级目录下创建templates

templates添加进TEMPLATE_DIRS我需要做以下设定,如果你也使用跟我一样的目录结构,你也需要同样的设定。

PROJECT_DIR = os.path.dirname(__file__)  

TEMPLATE_DIRS = (
os.path.join(PROJECT_DIR, '../templates'),
)

我们需要为some_app创建home.html文件,然后你需要进入templates目录。所以创建templates/come_app/home.html,在文件中写入以下内容。

<html>
<body>
<h1>This is home for some_app</h1>
</body>
</html>

现在查看一下项目的目录结构,便于消除一些不清楚的地方。

~/staticvirt/test_project$ tree -I *.pyc
.
|-- manage.py
|-- some_app
| |-- __init__.py
| |-- models.py
| |-- tests.py
| |-- urls.py
| *-- views.py
|-- templates
| *-- some_app
| *-- home.html
*-- test_project
|-- __init__.py
|-- settings.py
|-- urls.py
*-- wsgi.py 4 directories, 11 files

我们不想想是.pyc文件,所以将他们做了过滤。

启动服务。请确保你做好了你的数据库设定。

(staticvirt)~/staticvirt/test_project$ python manage.py runserver

在浏览器中打开http://127.0.0.1:8000/some_app/home。从现在开始,我们称这个页面为some_app的home,你应该能够看到你刚写下的html的内容。

处理静态文件

让我们编辑下some_app中的home.html文件,并且在其中添加样式,现在还不存在任何样式文件,我们将在编辑好home.html中的代码后添加。

<html>
<head>
<link href="{{STATIC_URL}}styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>This is home for some_app</h1>
</body>
</html>

刷新some_app的home页面。你将不会看到任何变化,因为我们还没有创建样式文件。

同样,访问http://127.0.0.1/static/style.css,你将会看到一个404页面。

现在开始创建样式文件。因为我们想要在some_app的template中使用这个样式,所以我们将在some_appstatic/的子目录中创建。所以创建some_app/static/style.css,添加以下内容。

body
{
background-color: red;
}

再刷新some_app的home页面,你将会看到页面背景变成了红色。同样,访问http://127.0.0.1/static/style.css,你看到的不再是404页面,而是样式文件的内容。如果你看到这些变化,请确认你将some_app添加进了INSTALLED_APPS,并且重启了服务。

需要注意的地方

  • 我们没有对Django的默认静态文件设置做任何改变。我们完全保留了Django的settings.py中关于静态文件的设置。
  • 在开发中,你不需要在urls.py中关于静态文件做任何改变,不需要添加staticfiles_urlpatterns(),我经常对此感到疑惑。
  • 在开发中,你不需要执行python manage.py collectstatic

内部是怎么工作的

  • 首先,检索settings.py中所有关于静态文件的设置。
  • 他们是STATIC_URL, STATIC_ROOT, STATICFILES_FINDERS, STATICFILES_DIRS
  • 同样我们已经将'django.contrib.staticfiles'添加进了INSTALLED_APPS
  • 现在先不管STATIC_ROOTSTATICFILES_DIRS。即使你将他们注释或者删除,你的项目依然能够像现在一样工作。
  • 我们需要将'django.contrib.staticfiles'添加进INSTALLED_APPS,如果我们想要使用Django默认的静态文件处理服务。
  • 所谓的Django默认的静态文件处理服务就相当于需要使用Django提供的python manage.py runserver
  • Django默认会在STATIC_URL下处理静态文件。注意STATIC_URL已经设置为'/static/'。这就是为什么我们获取到了我们的静态文件,举个例子,样式文件在这个url下http://127.0.0.1:8000/static/styles.css

    如果你访问http://127.0.0.1:8000/static_changed/styles.css,你将会得到一个404页面。如果你想要在http://127.0.0.1:8000/static_changed/styles.css提供,需要设置STATIC_URL = '/static_changed/'。现在动手试试吧。这只是为了举例说明STATIC_URL的用处,现在都改回默认设置,即STATIC_URL = '/static/'
  • 下一个问题是,Django是怎么知道从哪里去读取静态文件的,或者说怎么知道去哪里找到静态文件呢?这就是STATICFILES_FINDERS的作用了。

    STATICFILES_FINDERS中我们有两条记录:
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder'

现在你可以先不管FileSystemFinder,如果你愿意,你可以先注释掉这一行。AppDirectoriesFinder告诉Django从INSTALLED_APPS中每一个app下的static/ 子目录下去寻找静态文件。记住,我们是将style.css放在了some_app中static/子目录下,这就是为什么Django能够找到它,并且进行正确的处理。如果你将'static/'子目录修改为其他名字,你的静态文件就不能被正确处理了。动手试一试吧。注释掉AppDirectoriesFinder这一行,然后访问http://127.0.0.1:8000/static/styles.css,现在样式文件不能被正确地处理了。好,尝试过后去掉注释。

现在,我们知道了STATIC_URLSTATICFILES_FINDERS的作用。我们现在仍然不需要用到STATIC__ROOTSTATICFILES_DIRS

为了了解一些其他的事情关于静态文件的处理,我们需要另一个app。

创建一个。

python manage.py startapp other_app

修改项目的urls.py,将other_app包括进去。现在项目的urls.py包括两行。

url(r'^some_app/', include('some_app.urls')),
url(r'^other_app/', include('other_app.urls')),

我们需要在other_app的urls.py中添加几行,比如,在other_app/urls.py中:

url(r'^home$', direct_to_template, {"template": "other_app/home.html"})

现在在templates目录下创建other_app/home.html

<html>
<body>
<h1>This is home for other_app</h1>
</body>
</html>

查看一下现在的目录结构。

~/staticvirt/test_project$ tree -I *.pyc
.
|-- manage.py
|-- other_app
| |-- __init__.py
| |-- models.py
| |-- tests.py
| |-- urls.py
| *-- views.py
|-- some_app
| |-- __init__.py
| |-- models.py
| |-- static
| | *-- styles.css
| |-- tests.py
| |-- urls.py
| *-- views.py
|-- templates
| |-- other_app
| | *-- home.html
| *-- some_app
| *-- home.html
*-- test_project
|-- __init__.py
|-- settings.py
|-- urls.py
*-- wsgi.py

other_app添加进INSTALLED_APPS

现在访问url:http://127.0.0.1:8000/other_app/home

为other_app的home页面添加样式。假设我们想让它的背景颜色为蓝色,我们创建other_app/static/other_style.css

body{
background-color: blue;
}

将样式文件添加进other_app的home页面的模板中,将templates/other_app/home.html改为:

<html>
<head>
<link href="{{STATIC_URL}}other_style.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>This is home for other_app</h1>
</body>
</html>

刷新http://127.0.0.1:8000/other_app/home,你将会看到蓝色背景。你也许需要重启服务才能看到变化。同样,我们能够在http://127.0.0.1:8000/static/other_style.css中看到样式文件的内容。

同时,访问http://127.0.0.1:8000/some_app/home,验证下some_app的home页面依然是红色背景。

这里发生了什么

当我们发起一个/static/other_style.css的请求,Django知道STATIC_URL设置为'/static/',这跟url提供的第一个部分相匹配,因此它推断我们想要将其作为静态文件处理,所以它进入所有app的static/子目录中进行查找,因为STATICFILES_FINDERS包含了'django.contrib.staticfiles.finders.AppDirectoriesFinder'。当它在other_app中的static/目录下找到一个名为other_style.css的文件,就对它进行处理。

然而,这带来了另一个问题,你一定注意到了我们将other_app中的样式文件命名为other_style.css。如果我们想要它的名称也为style.css会发生什么呢?试试看。

mv other_app/static/other_style.css other_app/static/styles.css

同时,我们需要修改other_app的home文件来引入这个样式文件。我们必须做这个,因为我们将other_style.css改名为了style.css。other_app的home文件修改如下:

<html>
<head>
<link href="{{STATIC_URL}}styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>This is home for other_app</h1>
</body>
</html>

现在查看两个我们创建的页面。

http://127.0.0.1:8000/some_app/home
http://127.0.0.1:8000/other_app/home

你会发现现在两个页面的背景都变成了红色。这依赖于INSTALLED_APPS中app的排列顺序。如果some_appother_app的前面,两个页面都会是红色背景。如果other_appsome_app的前面,那么两个页面背景都是蓝色。在我的设置中,some_appother_app之前,所以背景都是红色的。

为什么这会发生

两个页面都想引用一个名为style.css的静态文件。Django尝试在INSTALLED_APPS中列出的所有app中的static/子目录下寻找这个文件。一旦它在some_app的static/子目录中找到了,就会进行处理并且不再继续在other_app中进行寻找。因此,some_app中static/子目录下将背景设置为红色,那么两个页面都被设置为红色背景了。

怎么避免

那么,如果我们想在两个app中样式文件都叫做style.css怎么做?这时候,我们需要在没一个app下的static/目录下增加一层目录,将其命名为各自app的名称。像下面这么做:

mkdir some_app/static/some_app
mv some_app/static/styles.css some_app/static/some_app
mkdir other_app/static/other_app
mv other_app/static/styles.css other_app/static/other_app/

我们在每一个app下的static/子目录下创建一个与各自app相同的目录。然后将样式文件移到这个目录下。

同理,也需要修改各自的模板文件。

修改templates/some_app/home.html中的stylesheet路径,新的内容如下:

<html>
<head>
<link href="{{STATIC_URL}}some_app/styles.css" rel="stylesheet" type="text/css"> </head>
<body>
<h1>This is home for some_app</h1>
</body>
</html>

templates/other_app/home.html做相似的改动。

<html>
<head>
<link href="{{STATIC_URL}}other_app/styles.css" rel="stylesheet" type="text/css">
</head>
<body>
<h1>This is home for other_app</h1>
</body>
</html>

现在再次查看两个页面。

http://127.0.0.1:8000/some_app/home
http://127.0.0.1:8000/other_app/home

你将会发现一个背景是红色,另一个是蓝色。

这里发生了什么

  • some_app的模板需要引用http://127.0.0.1:8000/static/some_app/styles.css
  • Django发现这个url以'/static/'开头,这跟STATIC_URL匹配,推测这需要处理静态文件some_app/style.css
  • 它开始在所有app的static/子目录中寻找文件some_app/style.css
  • 它最终在some_app的static/子目录中找到了它,并进行处理。
  • other_app的模板需要引用http://127.0.0.1:8000/static/other_app/styles.css
  • Django开始在所有app的static/子目录中寻找文件other_app/style.css
  • 它最终在other_app的static/子目录中找到了它,并进行处理。

希望你现在对于STATIC_URL, STATICFILES_FINDERS和静态文件是怎么处理的更加清楚了。

关于STATICFILES_DIRS

到现在我们假定我们在some_appother_app是需要各自独立的静态文件,所以我们为他们写了不同样式文件。

假定我们项目中一些样式需要保持一致,没一个app都没有特殊。这也的话,我们不需要将这些样式文件放进任何一个app的static/子目录中。我们在manage.py的同级目录中创建一个目录,然后将项目共同的静态资源放在这个目录中。

然我们看看是怎么做的。

在manage.py的同一级下创建一个名为project_static的目录。

mkdir project_static

创建一个名为base.css的文件,放进去。

touch project_static/base.css

编辑这个页面,包含以下内容:

h1
{
font-style: italic;
}

我们想让项目中所有h1标签中的内容斜体显示。

Django现在还不知道这个文件,也不知道怎么进行处理。要让Django知道它,需要将包含这个文件的目录添加进STATICFILES_DIRS。所以编辑test_project/settings.py,将需要的目录添加进STATICFILES_DIRS。

STATICFILES_DIRS = (
os.path.join(PROJECT_DIR, '../project_static'),
)

试着访问http://127.0.0.1:8000/static/base.css,你应该能看到刚才写的样式。请确保在STATICFILES_FINDERS中你设置了:

'django.contrib.staticfiles.finders.FileSystemFinder'

否则你将得到一个404页面。

这里发生了什么

  • Django服务器收到一个关于静态文件的请求,因为是一个以'/static/'开头的url。
  • 它开始在STATICFILES_DIRS设定的所有目录中寻找这个静态文件,比如base.css。
  • 由于我们在STATICFILES_DIRS中指定了一个目录,即project_static,Django服务器在这个目录中尝试寻找这个文件。它在这个目录中进行搜索时找到了这个文件,然后进行处理。
  • 如果没有在STATICFILES_DIRS指定的目录中找到这个文件,它将会在INSTALLED_APPS下所有app的static/子目录尝试寻找。
  • 注意,这时候依然没有不需要添加staticfiles_urlpatterns()

为了在模板中使用这个文件,我们需要引用这个样式。在所有模板中添加进下面这行。

<link href="{{STATIC_URL}}base.css" rel="stylesheet" type="text/css">

刷新两个页面的url,你将会看到这些页面中h1标签中的字体都为斜体。

让我们查看最终的目录结构,如果你有什么问题可以有帮助。

(staticvirt)~/staticvirt/test_project$ tree -I *.pyc
.
|-- manage.py
|-- other_app
| |-- __init__.py
| |-- models.py
| |-- static
| | *-- other_app
| | *-- styles.css
| |-- tests.py
| |-- urls.py
| *-- views.py
|-- project_static
| *-- base.css
|-- some_app
| |-- __init__.py
| |-- models.py
| |-- static
| | *-- some_app
| | *-- styles.css
| |-- tests.py
| |-- urls.py
| *-- views.py
|-- templates
| |-- other_app
| | *-- home.html
| *-- some_app
| *-- home.html
*-- test_project
|-- __init__.py
|-- settings.py
|-- urls.py
*-- wsgi.py 11 directories, 20 files

关于STATIC_ROOT

  • 如果在开发阶段你使用Django的runserver,你将永远不会需要STATIC_ROOT。
  • 一旦你需要进入生产,你能在服务器中使用它。Django提供了一个静态文件管理的命令叫做collectstatic,它将收集所有的静态资源,(如在STATICFILES_DIRS中找到的和在所有app下的static/子目录中找到的静态资源),将它们放进一个STATIC_ROOT定义的位置。
  • STATIC_ROOT只有在你使用collectstatic命令的时候才会有用处。

让我们验证一下,创建一个名为static_resources的目录.

mkdir static_resources

修改settings.py,添加以下几行.

STATIC_ROOT = os.path.join(PROJECT_DIR, '../static_resources')

现在运行命令:

python manage.py collectstatic

它会请求你确认,输入'yes',然后你将会看见所有的静态资源被收集进一个你在STATIC_ROOT定义的目录中。

然后在生产服务器中你可以设置所有的静态文件请求都进入STATIC_ROOT定义的目录中进行查找。

再说一次,关于STATIC_ROOT的部分只是附带着说说。在开发阶段你都不需要用到它。

            </div>
</div>
posted @
2015-06-22 00:57 
奋斗终生 
Views(...) 
Comments(...) 
Edit 
收藏

Django中对静态文件的支持(转)的更多相关文章

  1. django中的静态文件

    静态文件 1.什么是静态文件 在django中静态文件是指那些图片.css样式.js样式.视频.音频等静态资源. 2.为什么要配置静态文件 这些静态文件往往不需要频繁的进行变动,如果我们将这些静态文件 ...

  2. 在django中访问静态文件(js css img)

    刚开始参考的是别的文章,后来参考文章<各种 django 静态文件的配置总结>才看到原来没有但是没有注意到版本,折腾了一晚上,浪费了很多很多时间.后来终于知道搜索django1.7访问静态 ...

  3. django中关于静态文件的引入(这边是指边主要是jquery和bootstrap

    一.  创建文件夹 首先在项目的根目录中新建一个文件夹,这个文件夹的名称最好以static命名 二.   修改配置 在项目的settings文件中,拉倒最下面,可以看到 STATICFILES_DIR ...

  4. Django中使用静态资源/文件

    Django中常需要引用js,css,小图像文件,一般我们把这一类文件称为静态文件,放置在static文件夹中,接下来,对Django中配置静态文件进行下傻瓜式的步骤介绍 在工程目录下新建static ...

  5. Django (七) token&静态文件&媒体文件

    token&静态文件&媒体文件 1. token 1. 会话技术 2. 服务端会话技术 3. 它实际上就是手动实现的session 4. 实现token 4.1 在models.py中 ...

  6. 擦他丫的,今天在Django项目中引用静态文件jQuery.js 就是引入报错,终于找到原因了!

    擦 ,今天在Django项目中引用静态文件jQuery.js 就是引入报错,终于找到原因了! 问题在于我使用的谷歌浏览器,默认使用了缓存,导致每次访问同一个url时,都返回的是缓存里面的东西.通过谷歌 ...

  7. django项目部署在Apache服务器中,静态文件路径的注意点

    django Apache部署静态文件的路径注意点 静态文件放在对应的 app 下的 static 文件夹中 或者 STATICFILES_DIRS 中的文件夹中. 当 DEBUG = True 时, ...

  8. day52_9_16Django中的静态文件和orm

    一.静态文件配置 在配置静态文件时,需要创建一个文件夹在Django项目文件夹下,名字与使用无关. 静态文件包括html等使用的不会变动的插件文件等.分为三个部分: css文件夹 当前网站所有的样式文 ...

  9. django加载静态文件

    在一个网页中,不仅仅只有一个 html 骨架,还需要 css 样式文件. js 执行文件以及一些图片等,因此在 DTL 中加载静态文件是一个必须要解决的问题.在 DTL 中,使用 static 标签来 ...

随机推荐

  1. hdu 1006 Tick and Tick 有技巧的暴力

    Tick and Tick Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Tot ...

  2. vs2015开发so动态库linux

    #include <stdio.h> #include <dlfcn.h> typedef int(*fn_max)(int a, int b); int main() { p ...

  3. 基于HTML5堆木头游戏

    今天要来分享一款很经典的HTML5游戏——堆木头游戏,这款游戏的玩法是将木头堆积起来,多出的部分将被切除,直到下一根木头无法堆放为止.这款HTML5游戏的难点在于待堆放的木头是移动的,因此需要你很好的 ...

  4. Eclipse中安装JBoss Tools插件

    1.先访问JBoss Tools网站,看看上面怎么说: http://tools.jboss.org -> 进入下载界面 看到下面这句话: Drag and drop this  icon in ...

  5. 网桥bridge

    1. 网桥基础 什么是网桥 网桥将多个网络在数据链路层连接起来.网桥的前身是集线器或中继器.网桥和集线器的区别:集线器上各端口都是共享同一条背板总线的,网桥的两个端口分别有一条独立的交换信道,不是共享 ...

  6. linux 链接的使用 创建和删除符号连接(软、硬链接)

    1 . 使用方式 :ln [option] source_file dist_file   (source_file是待建立链接文件的文件,dist_file是新创建的链接文件)            ...

  7. sqlserver、mysql怎样获取连接字符串

    sqlserver.mysql怎样获取连接字符串 步骤: 一.新建文本文档xxx.txt,改动文件类型为.udl 二.打开该文件,在<提供数据>中找到相应的服务. 三.在连接中选择须要的数 ...

  8. 浅谈NFC、RFID、红外、蓝牙的区别

    很多朋友对NFC和RFID这两个词感到陌生,但是手机经常会出现支持NFC支付,又没太在意,NFC与RFID其实是手机支付的种方式(手机支付也被称作移动支付,是一种允许移动用户使用其移动终端对所消费的商 ...

  9. MySQL线程池总结

    线程池是Mysql5.6的一个核心功能,对于服务器应用而言,无论是web应用服务还是DB服务,高并发请求始终是一个绕不开的话题.当有大量请求并发访问时,一定伴随着资源的不断创建和释放,导致资源利用率低 ...

  10. java开发总体知识复习

    上一篇发了一个找工作的面经, 找工作不宜, 希望这一篇的内容能够帮助到大家. 对于这次跳槽找工作, 我准备了挺长的时间, 其中也收集了很多比较好的笔试面试题, 大都是一些常用的基础, 很多都是由于时间 ...