¶静态文件
静态文件的配置,一般需要使用到以下几个参数
1 | STATIC_URL |
¶STATIC_URL
STATIC_URL
是必须设置的,提供了静态文件访问的映射关系,如设置 STATIC_URL='/static/'
时(名字可以自定义,这个是访问所有的静态文件的根名),访问静态文件的路径就是 127.0.0.1:8000/static/静态文件名
。在设置了该参数之后,Django实际上就有了访问静态文件的能力,所以说该参数是必须设置的。
在开发模式下(DEBUG设置为True),Django提供了静态文件代理的功能,会自动识别每个 app下静态文件(前提是,这些静态文件夹必须设置在每个app之下,且使用的名字必须是static,这是因为Django内部做了相应的处理,只有名字 static
才会被Django自带的静态文件代理服务器识别),提供访问。
设置app下的静态文件夹的时候,内部最好有一个用当前app名字命名的文件夹,并在该文件夹下放置相应的静态文件(这是因为不做区分,万一多个app之间有同名的静态文件,Django就会混淆),此时这些静态文件的访问地址就是: 127.0.0.1:8000/static/app命名的文件夹/相应的静态文件
例如,第三方插件xadmin这个app就是这样设计的:
此外,设置了该参数之后,在模板层通过引入 { % load staticfiles % }
[1]标签,可以在模板中使用 href="{ % static 'css/reset.css' % }"
[1:1] 构建静态资源路径的构建,这样当对 STATIC_URL
指定的静态文件的根名方法改变的时候,不需要修改模板中的访问路径,依然能够访问,效果和{ % url '' % }
[1:2]类似。
¶STATICFILES_DIRS
只在开发模式下有效,对于一些公共的静态文件,或者在项目中自建app的时候不想为每个app单独设置静态文件夹,为了方便管理,可以单独在项目的根目录下设置一个文件夹统一管理所有的静态文件(但是这个文件夹无法被开发模式下Django自带的静态文件代理服务定位到,所以必须使用STATICFILES_DIRS进行设置),设置如下:
1 | # 全局静态文件访问配置 |
这样在项目根目录下创建 集中管理的文件名
文件,在里面放置静态文件,此时静态文件的访问地址是 127.0.0.1:8000/static/集中管理的文件名中的静态文件
。
STATICFILES_DIRS 的设置只是提供给开发模式下的Django自带静态文件代理服务定位静态文件用的。
¶STATIC_ROOT
在Django项目部署上线的时候,DEBUG需要设置为False,Django 不再提供静态文件代理功能,app自带的静态文件夹分布在各app下无法访问到,此时需使用 pyhton manage.py collectstatic
收集所有的静态文件,STATIC_ROOT就是用来设置所有的静态文件的聚合目录,如:
1 | STATIC_ROOT = os.path.join(BASE_DIR, 'static') |
使用 python manage.py collectstatic
之后,django会把所有的static文件都复制到STATIC_ROOT文件夹下。
¶小结
- 无论是开发模式还是生产环境下,Django项目都依赖STATIC_URL=’/static/'的设置,因为这提供了静态文件访问的映射关系,有了他,Django才能够访问静态文件。
- STATICFILES_DIRS用于指定在项目根目录下统一管理的静态文件夹的名字,但只是在开发过程中有效以及使用,生产环境下,所有的静态文件都将被收集到统一的目录下(包括 STATICFILES_DIRS 的),交给第三方静态服务器调度提供。
- 若存在app下的static和STATICFILES_DIRS设置中同名的文件,默认访问的是STATICFILES_DIRS设置的静态文件下的,所以在app下的static中再设置一个app名的文件夹对静态文件管理,这样在访问时加上app名127.0.0.1:8000/static/app名,这样可以有效避免一些重名问题。
- 关于static目录的位置设置使用建议,若website中的每个app的独立性非常强的话,就在每个单独的app下设置static目录,这样app就会支持热插拔,独立性强。若app的独立性不强,app之间相互联系的话,建议使用集中管理static的方法。但是无论使用哪种方式,在项目部署的时候,都会进行静态文件的收集,由第三方静态服务器管理。
¶media文件
设置和static类似,因为在开发模式下(DEBUG需要设置为True),Django并不提供media文件的代理服务,所以即使在开发模式下,也需要手动设置medai文件的代理。
¶配置
需要同时设置MEDIA_URL和MEDIA_ROOT
1 | # media文件的路径 |
解释:
设置MEDIA_ROOT
后,Django做了一定的处理,能够使上传的文件传到MEDIA_ROOT
指定的文件中,如models.py中指定的模型有些有 upload_to="org/%Y/%m"
,这样指定后,就会在media中创建 org/年/月
的文件夹存储文件。此时仅仅设置 MEDIA_ROOT
参数,就可以完成上传时自动放到设置的media目录下。但是此时的图片访问地址是当前所在页面的地址,加上存储的地址,为当前所在地址/org/%Y/%m/图片
。
若想访问到meida中的地址,还需要设置MEDIA_URL="/media/"
,设置之后访问media的路径就变成了127.0.0.1:8000/media/org/%Y/%m/图片
。但是目前通过这个地址还是访问不了media(这点和static不同),Django没有对media的访问做处理,还需要我们手动对url的访问处理:
1 | # 在项目urls.py中设置url |
1 | from django.views.static import serve |
此时就完成了media文件的访问。
¶问题
媒体文件都是通过models.py中模型通过设置 upload_to
字段将文件的路径存储在数据库中,文件存储在MEDIA_ROOT设置的路径之中,所以在使用的时候,数据库中只能读取到 upload_to
时的路径 /org/年/月/文件名
,而这个路径是不完整的,想要访问到文件还需要添加MEDIA_URL设置的前缀。
在模板层中想要获得MEDIA_URL设置的前缀可以view视图进行传递,然后在模板层中使用 data-url="{ { MEDIA_URL } } { { org.image } }"
[1:3],但是这样写的话,意味着要在每个views中传递MEDIA_URL参数,这是非常不好的。可以使用类似注入的方式,将MEDIA_URL注入到模板中,使其可以在模板中直接被调用。
Django自带了一些注入,如在模板中,直接可以使用{ % if request.user.is_authenticated % }
[1:4]调用request.user设置直接使用user进行操作,这是因为在settings.py中的进行了如下的设置:
1 | TEMPLATES = [ |
django中已经提供好了django.template.context_processors.media
只要添进去即可
我们看一下这个函数media的逻辑:
1 | def media(request): |
逻辑相当简单,这样我们也可以模仿使用类似的方式定义我们自己的context_processors
之后再模板中使用图片的方式为:src="{ { MEDIA_URL } }{ { hot_course.image } }"[1:5]
若不不使用模板层的context_processors
注入方法,还可以使用image model(models.ImageField)的自带属性方法url,他会自动拼接形成一个可以方法的url,如src="{ { hot_course.image.url } }"[1:6]。实际使用中也推荐使用该种方法,因为不需要做额外的操作,直接调用图片属性的url,即可自动拼接成图片相应的访问地址。