项目部署到阿里云(nginx+uwsgi)上后,静态文件加载没有问题。但是在本地,使用开发服务器,却始终加载不成功。
settings\common.py:
STATIC_ROOT = os.path.join(BASE_DIR, 'xxx/yyy/static/')
#STATICFILES_FINDERS = (
# 'django.contrib.staticfiles.finders.FileSystemFinder',
# 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
#)
INSTALLED_APPS = [
#'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sites',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
...
]
STATICFILES_DIRS = [
# os.path.join(BASE_DIR, 'xxx/yyy/static'),
]
STATIC_URL = '/static/'
settings\dev.py:
from .common import *
#是否注释STATICFILES_FINDERS,对runserver --nostatic情况下,加载静态文件没有任何影响,都可以正常显示;
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
#STATICFILES_FINDERS = (
# 'django.contrib.staticfiles.finders.FileSystemFinder',
# 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
#)
settings\prod.py:
from .common import *
from django.conf.urls.static import static
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
#Added at 20170428 开发环境下,如果注释掉,无法正确加载静态文件
#urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
执行python manage.py runserver
浏览器输入http://127.0.0.1:8000/ 后,可见各种静态文件没有正确加载。
浏览器Dev模式下,显示404错误。
浏览器输入http://127.0.0.1:8000/static/site/v1/img/LOGO.PNG 后,显示同样的错误404。
执行python manage.py runserver --nostatic
浏览器输入http://127.0.0.1:8000/ 后,各种静态文件正确加载。
浏览器输入http://127.0.0.1:8000/static/site/v1/img/LOGO.PNG 后,可以正确加载。
静态文件
生产环境
静态文件交由Web Server处理,Django本身不处理静态文件。简单的处理逻辑如下(以nginx为例):
URI请求 --->>> Web Server
按照Web Server里面的配置规则处理(以nginx为例,主要配置在nginx.conf里面的location参数。),如果是静态文件,则由nginx直接处理;如果不是,则交由Django处理,Django会根据urls.py里面的规则进行匹配。
开发环境
以上是部署到Web服务器后的处理方式,为了便于开发,Django提供了在开发环境下对静态文件的处理机制,方法是这样的(可能是低版本的步骤,仅供理解用,步骤谨慎怀疑):
1.在INSTALLED_APPS
里面加入'django.contrib.staticfiles'
;
2.在urls.py里面加入:
if settings.DEBUG:
urlpatterns += patterns('', url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }),
url(r'^static/(?P<path>.*)$','django.views.static.serve',{'document_root':settings.STATIC_ROOT}), )
3.这样就可以在开发阶段直接使用静态文件了。
MEDIA_ROOT和MEDIA_URL
静态文件的处理包括STATIC和MEDIA两类,这往往容易混淆,在Django里面是这样定义的:
MEDIA指用户上传的文件,比如在Model里面的FileField、ImageField
上传的文件。如果你定义MEDIA_ROOT=C:\temp\media
,那么File = models.FileField(upload_to='abc/')
,上传的文件就会被保存到C:\temp\media\abc
。
举个例子:
class blog(models.Model):
Title=models.charField(max_length=64)
Photo=models.ImageField(upload_to="photo")
上传的图片就是上传到c:\temp\media\photo
,而在模板中要显示该文件,则这样写{{MEDIA_URL}}blog.Photo
。
在settings里面设置的MEDIA_ROOT必须是本地路径的绝对路径,一般是这样写,
PROJECT_PATH = os.path.abspath(os.path.dirname(__file__))
MEDIA_ROOT=os.path.join(PROJECT_PATH,'media/').replace('\\','/')
MEDIA_URL
是指从浏览器访问时的地址前缀,举个例子:
MEDIA_ROOT=c:\temp\media\photo
MEDIA_URL="/data/" #可以随便设置
在开发阶段,media的处理由Django处理:访问http://localhost/data/abc/a.png 就是访问 c:\temp\media\photo\abc\a.png
,在模板里面这样写({{MEDIA_URL}}abc/a.png)
,在部署阶段最大的不同在于你必须让web服务器来处理media文件,因此你必须在web服务器中配置,以便能让web服务器访问media文件。
以nginx为例,可以在nginx.conf里面这样写:
location ~/media/{
root /temp/
break;
}
具体可以参考如何在nginx部署Django的资料。
STATIC_ROOT和STATIC_URL
STATIC主要指的是如css、js、images这样的文件,在settings里面可以配置STATIC_ROOT
和STATIC_URL
配置方式与MEDIA_ROOT
是一样的,但是要注意STATIC_ROOT
与MEDIA_ROOT
位置不能一样。
STATIC文件一般保存在以下位置:
-
STATIC_ROOT
:在settings里面设置,一般用来放一些公共的js,css,image等。 - APP的static文件夹,在每个APP所在文件夹中可以建立一个
static
文件夹,然后当运行collectstatic
时,Django会遍历INSTALL_APPS
里面所有APP的static文件夹,将里面所有的文件复制到STATIC_ROOT
。因为,如果你要建立可复用的APP,那么你要将该APP所需要的静态文件放在static文件夹中。
也就是说一个项目引用了很多app,那么这个项目所需要的css, images等静态文件是分散在各个app的static文件的,比较典型的是admin应用。当你要发布时,需要将这些分散的static文件收集到一个地方就是STATIC_ROOT
。 - STATIC文件可以配置
STATICFILES_DIRS
,用以指定额外的静态文件存储位置。
STATIC_URL
的含义与MEDIA_URL
类似。
如果在部署阶段找不到css,js,则可能是一下几个问题:
1.web服务器配置有问题,不同的部署方式对静态文件的处理有所不同;
2.没有运行collectstatic
将所需要的静态文件收集到STATIC_ROOT
。
MEDIA_ROOT
: 主要是为了存放上传的文件,比如在ImageField
中,这个值加上upload_to
的值就是真实存放上传图片的文件位置;
Django里,文件内容实际上是不会存放到数据库里边的,大多数数据库存放效率低,需要保存在文件系统里。
MEDIA_URL
: URL
的映射,前后要加上"/"表示从根目录开始,比如"/site_media/"
,加上这个属性之后,静态文件的链接前面会加上这个值。
STATIC_ROOT
:这个文件里面的目录会当成静态文件处理。
STATIC_URL
: URL映射,指定静态目录的URL,默认是"/static/"
。
STATICFILES_DIRS
:指定一个工程里边哪个目录存放了与这个工程相关的静态文件,是一个列表。如果列表中有一个是“/home/shishang/test/static”
,其中有一个文件内容是productlist.html
,我们只要访问http://localhost:8000/static/productlist.html
就可以直接访问了。
Django提供了一个方法自动地将所有的静态文件放在一起。只要在写App的时候创建一个static子目录专门保存静态文件就行了。在开发阶段,不必费心去做映射,不需要配置urls.py。在部署到生产环境的时候,只需要配置Apache
把/static/
映射到STATIC_ROOT
,然后运行manage.py collectstatic
,自动地STATICFILES_DIR
列出的目录以及各个APP下的static子目录的所有文件复制到STATIC_ROOT
。因为复制过程可能会覆盖掉原来的文件,所以,一定不能把我们辛苦做出来静态文件放这边!在开发阶段,Django把/static
映射到django.contrib.staticfiles
这个APP。staticfiles
自动地从STATICFILES_DIRS
、STATIC_ROOT
以及各个App子目录里面搜索静态文件。一旦部署到开发环境上,settings.py
不需要重新编写,只要在Apache
的配置文件里面写好映射,/static
将会被Apache处理。django.contrib.staticfiles
虽然仍然存在,但因为不会接收到以/static/开始的路径,所以将不会产生作用。不必担心Django会使处理速度变慢。另外,当settings.DEBUG is False
的时候,staticfiles
将自动关闭。
内部是怎么工作的?
- 首先,检索
settings.py
中所有关于静态文件的设置,它们是STATIC_URL,STATIC_ROOT, STATICFILES_FINDERS, STATICFILES_DIRS
。 - 同样我们已经将
'django.contrib.staticfiles'
添加进了INSTALLED_APPS
。 - 现在先不管
STATIC_ROOT
和STATICFILES_DIRS
。即使你将它们注释或者删除,你的项目依然能够像想在一样工作。 - 我们需要将
'django.contrib.statifiles'
添加进INSTALLED_APPS
,如果我们想要使用Django默认的静态文件处理服务。 - 所谓Django默认的静态文件处理服务就相当于需要使用Django提供的
python manage.py runserver
。 - Django默认在
STATIC_URL
下处理静态文件。注意STATIC_URL已经设置为‘/static/’。这就是为什么我们获取到了我们的静态文件,举个例子,样式文件在这个url下http://127.0.0.1:8000/static/style.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
。
这里发生了什么?
- Django服务器收到一个关于静态文件的请求,应该是一个以
'/static/'
开头的url。 - 它开始在
STATICFILES_DIRS
设定的所有目录中寻找这个静态文件,比如base.css
。 - 由于我们在
STATICFILES_DIRS
中指定了一个目录,即project_static
,Django服务器在这个目录中尝试寻找这个文件。它在这个目录中进行搜索时找到了这个文件,然后进行处理。 - 如果没有在
STATICFILES_DIRS
指定的目录中找到这个文件,它将会在INSTALLED_APPS
下所有app的static/
子目录尝试寻找。
注意,这时候依然不需要添加staticfiles_urlpatterns()
。
关于STATIC_ROOT
- 如果在开发阶段使用
Django
的runserver
,你将永远不会需要STATIC_ROOT
。 - 一旦你需要进入生产,你能在服务器中使用它。
Django
提供了一个静态文件管理的命令叫做collectstatic
,它将收集所有的静态资源,(如在STATICFILES_DIRS
中找到的和在所有app下的static/子目录中找到的静态资源),将它们放进一个STATIC_ROOT
定义的位置。
STATIC_ROOT
只有你在使用collectstatic
命令的时候才会有用处。
Refer to:
- http://blog.csdn.net/fighter_yy/article/details/41249033
- http://www.tuicool.com/articles/BjIBJi
- http://lanceverw.iteye.com/blog/1798037
settings
Django的STATICFILES_FINDERS设置项是一个列表,它包含了若干个知道如何从不同地点寻找静态文件的搜寻器。其中之一是AppDirectoriesFinder,它会从INSTALLED_APPS中各个应用的'static'子目录中寻找文件。
STATICFILES_FINDERS
Default:
[
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]
The list of finder backends that know how to find static files in various locations.
The default will find files stored in the STATICFILES_DIRS
setting(using django.contrib.staticfiles.finders.FileSystemFinder
) and in a static subdirectory of each app(using django.contrib.staticfiles.finders.AppDirectoriesFinder
). If multiple files with the same name are present, the first file that is found will be used.
One finder is disabled by default:
django.contrib.staticfiles.finders.DefaultStorageFinder
. If added to your STATICFILES_FINDERS
settings, it will look for static files in the default file storage as defined by the DEFAULT_FILE_STORAGE
setting.
Refer: https://docs.djangoproject.com/en/1.11/ref/settings/
STATICFILES_STORAGE
Default: 'django.contrib.staticfiles.storage.StaticFilesStorage'
The file storage engine to use when collecting static files with the collectstatic
management command.
A ready-to-use instance of the storage backend defined in this setting can be found at django.contrib.staticfiles.storage.staticfiles_storage
.
The staticfiles app
django.contrib.staticfiles
collects static files from each of your appliations(and any other places you specify) into a single location that can easily be served in production.
For an introduction to the static files app and some usage examples, seeManaging static files (e.g. images, JavaScript, CSS). For guidelines on deploying static files, see Deploying static files.
Management Commands
django.contrib.staticfiles
exposes three management commands.
collectstatic
django-admin collectstatic
Collects the static files into STATIC_ROOT
.
Duplicate files names are by default resolved in a similar way to how template resolution works: the file that is the first found in one of the speicified locations will be used. If you're confused, the findstatic
command can help show you which files are found.
On subsequent collectstatic
runs(if STATIC_ROOT
isn't empty),files are copied only if they have a modified timestamp greater than the timestamp of the file in STATIC_ROOT
. Therefore if you remove an application from INSTALLED_APPS
, it's a good idea to use the collectstatic --clear
option in order to remove stale static files.
Files are searched by using the enabled finders
. The default is to look in all locations defined in STATICFILES_DIRS
and in the 'static' directory of apps specified by the INSTALLED_APPS
setting.
The collectstatic
management command calls the post_process()
method of the STATICFILES_STORAGE
after each run and passes a list of paths that have been found by the management command. It also receives all command line options of collectstatic
. This is used by the CachedStaticFileStorage
by default.
For a full list of options, refer to the commands own help by running:
$python manage.py collectstatic --help
findstatic
django-admin findstatic staticfile [staticfile ...]
Searches for one or more relative paths with the enabled finders.
For example:
$ python manage.py findstatic css/base.css admin/js/core.js
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
Found 'admin/js/core.js' here:
/home/polls.com/src/django/contrib/admin/media/js/core.js
findstatic --first
By default, all matching locations are found. To only return the first match for each relative path, use the --first option:
$ python manage.py findstatic css/base.css --first
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
This is a debugging aid; it’ll show you exactly which static file will be collected for a given path.
By setting the --verbosity flag to 0, you can suppress the extra output and just get the path names:
$ python manage.py findstatic css/base.css --verbosity 0
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
On the other hand, by setting the --verbosity flag to 2, you can get all the directories which were searched:
$ python manage.py findstatic css/base.css --verbosity 2
Found 'css/base.css' here:
/home/special.polls.com/core/static/css/base.css
/home/polls.com/core/static/css/base.css
Looking in the following locations:
/home/special.polls.com/core/static
/home/polls.com/core/static
/some/other/path/static
runserver
django-admin runserver [addrport]
Overrides the core runserver command if the staticfiles
app is installed and adds automatic serving of static files and the following new options.
--nostatic
User the --nostatic option to disable serving of static files with the statifiles app entirely. This option is only available if the staticfiles
app is in your project's INSTALLED_APPS
setting.
Example usage:
django-admin runserver --nostatic
Storages存储
StaticFilesStorage
class storages.StaticFilesStorage
A subclass of the FileSystemStorage
storage backend that uses the STATIC_ROOT
setting as the base file system location and the STATIC_URL
setting respectively as the base URL.
storage.StaticFilesStorage.post_process(paths, **options)
This method is called by the collectstatic management command after each run and gets passed the local storages and paths of found files as a dictionary, as well as the command line options.
Other Helpers
There are a few other helpers outside of the staticfiles app to work with static files:
- The
django.template.context_processors.static()```` context processor which adds
STATIC_URLto every template context rendered with
RequestContext``` contexts. - The builtin template tag
static
which takes a path and url joins it with the static prefixSTATIC_URL
. Ifdjango.contrib.staticfiles
is installed, the tag uses theurl()
method of theSTATICFILES_STORAGE
instead.
Static file development view静态文件开发视图
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应用程序附带了一个快速和脏的帮助视图,可以使用它在开发中本地提供文件。
views.serve(request, path)
views.serve(request, path)
This view function serves static files in development. This view will only work if DEBUG is 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.
This view is automatically enabled by runserver (with a DEBUG
setting set to True). To use the view with a different local development server, add the following snippet to the end of your primary URL configuration:
from django.conf import settings
from django.contrib.staticfiles import views
if settings.DEBUG:
urlpatterns += [
url(r'^static/(?P<path>.*)$', views.serve),
]
Note, the beginning of the pattern (r'^static/') should be yourSTATIC_URL setting.
urls.staticfiles_urlpatterns()
urls.staticfiles_urlpatterns()
This will return the proper URL pattern for serving static files to your already defined pattern list. Use it like this:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
# ... the rest of your URLconf 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 in addition to files in app directories.
Refer to: https://docs.djangoproject.com/en/1.11/ref/contrib/staticfiles/
Managing static files(e.g. images,JS,CSS)
Websites generally need to serve additional files such as images, JavaScript, or CSS. In Django, we refer to these files as 'static files'. Django provides django.contrib.staticfiles
to help you manage them.
Configuring static files
- Make sure that
django.contrib.staticfiles
is included in your INSTALLED_APPS. - In your settings file, define STATIC_URL, for example:
STATIC_URL = '/static/'
- In your templates, either hardcode the url ike /static/my_app/example.jpg or, preferably, use the static template tag to build the URL for the given relative path by using the configured STATICFILES_STORAGE storage(this makes it much easier when you want to switch to a content delivery network(CDN) for serving static files).
{% load static %}
![]({% static )
- Store your static files in a folder called static in your app. For example, my_app/static/my_app/example.jpg
In addition to these configuration steps, you will also need to actually serve the static files.
During development, if you use django.contrib.staticfiles, this will be done automatically by runserver when DEBUG is set to True(see django.contrib.staticfiles.views.serve()).
This method is grossly inefficient and probably insecure, so it is unsuitable for production.
Your project will probably also have static asserts that aren't tied to a particular app. In addition to using a static/ directory inside your apps, you can define a list of directories(STATICFILES_DIRS) in your settings files where Django will also look for static files. For example:
STATICFILES_DIRS = [
os.path.join(BASE_DIR, "static"),
'/var/www/static/',
]
Serving static files during development
If you use django.contrib.staticfiles
as explained above, runserver will do this automatically when DEBUG is set to True. If you don't have django.contrib.staticfiles
in INSTALLED_APPS, you can still manually serve static files using the django.views.static.serve()
view.
This is not suitable for production use!
For example, if your STATIC_URL is defined as /static/, you can do this by adding the following snippet to your urls.py:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Note
Note: This helper function works only in debug mode and only if the given prefix is local(e.g. /static/) and not a URL(e.g. http://static.example.com/)
Also this helper function only serves the actual STATIC_ROOT folder; it does not perform static files discovery like django.contrib.staticfiles
.
Serving files uploaded by a user during development
During development, you can serve user-uploaded media files from MEDIA_ROOT
using the django.views.static.serve()
view.
This is not suitable for production use!
For example, if your MEDIA_URL is defined as /media/, you can do this by adding the follwing snippet to your urls.py:
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)