Django中对静态文件的支持(转)
2015-06-22 00:57
591 查看
英文原文:[]http://agiliq.com/blog/2013/03/serving-static-files-in-django/]
译文:[]http://segmentfault.com/a/1190000000358284]
处理静态文件,尤其是在开发时,是一件蛋疼的事情。在这篇文章中,我们将会讨论一些设置,目录结构和他们之间的相互影响。设置好
我们将会创建一个Django项目,这样可以让我们更好的了解我们讨论的这些这些文件在什么目录中。我们将会使用Django1.4,这些都也能在Django1.3中工作,因为没有在Django1.2下进行测试,所以对1.2版本下是否有问题不是很清楚。
我们将在命名为staticvirt的虚拟环境中做所有事情,所以我们需要命令
我们创建一个app,我们将会在里面创建一个template,然后会写一些静态文件,比如样式文件,然后在模板中使用这个样式文件。
我们需要一个
将templates添加进
启动服务。请确保你做好了你的数据库设定。
同样,访问
现在开始创建样式文件。因为我们想要在
在开发中,你不需要在urls.py中关于静态文件做任何改变,不需要添加staticfiles_urlpatterns(),我经常对此感到疑惑。
在开发中,你不需要执行
他们是
同样我们已经将'django.contrib.staticfiles'添加进了
现在先不管
我们需要将'django.contrib.staticfiles'添加进
所谓的Django默认的静态文件处理服务就相当于需要使用Django提供的
Django默认会在
如果你访问
下一个问题是,Django是怎么知道从哪里去读取静态文件的,或者说怎么知道去哪里找到静态文件呢?这就是
在
现在,我们知道了
为了了解一些其他的事情关于静态文件的处理,我们需要另一个app。
创建一个。
现在访问url:
为other_app的home页面添加样式。假设我们想让它的背景颜色为蓝色,我们创建
同时,访问
然而,这带来了另一个问题,你一定注意到了我们将
同理,也需要修改各自的模板文件。
修改
Django发现这个url以'/static/'开头,这跟
它开始在所有app的static/子目录中寻找文件
它最终在
Django开始在所有app的static/子目录中寻找文件
它最终在
希望你现在对于STATIC_URL, STATICFILES_FINDERS和静态文件是怎么处理的更加清楚了。
假定我们项目中一些样式需要保持一致,没一个app都没有特殊。这也的话,我们不需要将这些样式文件放进任何一个app的static/子目录中。我们在manage.py的同级目录中创建一个目录,然后将项目共同的静态资源放在这个目录中。
然我们看看是怎么做的。
在manage.py的同一级下创建一个名为project_static的目录。
Django现在还不知道这个文件,也不知道怎么进行处理。要让Django知道它,需要将包含这个文件的目录添加进STATICFILES_DIRS。所以编辑
它开始在
由于我们在
如果没有在
注意,这时候依然没有不需要添加
为了在模板中使用这个文件,我们需要引用这个样式。在所有模板中添加进下面这行。
让我们查看最终的目录结构,如果你有什么问题可以有帮助。
一旦你需要进入生产,你能在服务器中使用它。Django提供了一个静态文件管理的命令叫做collectstatic,它将收集所有的静态资源,(如在
STATIC_ROOT只有在你使用collectstatic命令的时候才会有用处。
让我们验证一下,创建一个名为
然后在生产服务器中你可以设置所有的静态文件请求都进入
再说一次,关于
译文:[]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_app的static/的子目录中创建。所以创建
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_ROOT和
STATICFILES_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_URL和
STATICFILES_FINDERS的作用。我们现在仍然不需要用到
STATIC__ROOT和
STATICFILES_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_app在
other_app的前面,两个页面都会是红色背景。如果
other_app在
some_app的前面,那么两个页面背景都是蓝色。在我的设置中,
some_app在
other_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_app和
other_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的部分只是附带着说说。在开发阶段你都不需要用到它。
相关文章推荐
- Algorithms—122.Best Time to Buy and Sell Stock II
- Algorithms—121.Best Time to Buy and Sell Stock
- Google GFS文件系统深入分析
- Google GFS文件系统深入分析
- poj3622 Gourmet Grazers(贪心+Treap)
- 学习Rust Book之写Cargo配置文件
- Uva - 11054 - Wine trading in Gergovia
- Uva - 11054 - Wine trading in Gergovia
- .pb.h:9:42: fatal error: google/protobuf/stubs/common.h: No such file or directory
- EGORefreshTableHeaderView学习
- django 简单会议室预约(1)
- OGRE1.7以上版本隐藏LOGO及鼠标拾取物体关键
- 使用 Google
- ubuntu 安装 google Gtest
- Django学习日记05_模板_模板语言
- Django学习日记04_模板_overview
- MIT algorithm 笔记(视频2)
- In machine learning, is more data always better than better algorithms?
- 返回书签 GotoBookmark
- django1.7写一个MOOC管理系统(一:基本配置)(2015.6.20)