![535aff40fca5a8b54c88ee87fa64ce7d.png](https://i-blog.csdnimg.cn/blog_migrate/c9071e64d96838a751df5e51e31e1300.jpeg)
原视频:Assets in Django without losing your hair - PyCon 2019
Django 处理静态资源相对而言是比较蛋疼的,该 talk 作者给我们介绍了 django app 处理静态资源的四个发展阶段(或者说场景),从最简单的单机文件系统,到前后端完全分离,希望能对你有所帮助。
0x01 Simple Assets
这种方式是最简单的,虽然效率可能相比下面介绍的要低,但是还是足够 handle 大多数业务场景,Don't Over Thinking! 这种开发模式用 collectstatic
将所有 app和 STATICFILES_DIRS
目录下的静态资源打包到到 STATIC_ROOT
目录。然后可以用 nginx
serve 静态资源,比如:
# django settings.py
STATIC_URL = '/static/'
# nginx server config
server {
...
location /static {
autoindex on;
alias /opt/aa/webroot/;
}
}
除了nginx,作者还介绍了一个工具: whitenosie
,文档在这里,有兴趣可以了解一下。
这个阶段的示意图如下所示:
![3c08dfcbae402ec928e64fc738848fd5.png](https://i-blog.csdnimg.cn/blog_migrate/32f3c9f092e4d7d1c3b1dbfa65533d6f.jpeg)
![6d164a5de1941fb57b38e6408ada1305.png](https://i-blog.csdnimg.cn/blog_migrate/c8db161985b0d02058949434f615c7f9.jpeg)
总结一下这个阶段:
- 使用 whitenoise。(我个人还是比较喜欢nginx)
- 关键配置为:
STATICFILES_DIRS
和STATIC_ROOT
。 - 模板语法不要硬编码!
![581a3eacffb985e92cab3c9b3ee3c414.png](https://i-blog.csdnimg.cn/blog_migrate/1bcdb9fa9ee321127fa111deb1bbcbcc.jpeg)
- 每次 deploy别忘了 collectstatic,有一个
--noinput
参数比较有用,这可以实现自动化,而不需要每次 collecstatic 都回答yes or no。
0x02 Cloud Stroage
可以用 S3、Azure、阿里云、七牛云来存储你的静态文件,这样访问速度肯定是要更快的,但是会对开发新增 complexity。django 有个第三方插件:django-storages,但是目前好像还不支持国内的CDN 服务商,比如阿里云、七牛云,当前你完成可以自己写。
比如如果你想使用 Amazon s3存储:
![59529735a0063a84df41b0d21af0125b.png](https://i-blog.csdnimg.cn/blog_migrate/b4849b7e0947cedb00dd6a384f5ad159.png)
django 的配置文件:
![946946cb2553cbdee28f49da0de330d0.png](https://i-blog.csdnimg.cn/blog_migrate/745aff1adeb254ca062e9dc91e9dad0e.jpeg)
其中最关键的配置为: STATICFILES_STORAGE
,它的默认值为 django.contrib.staticfiles.storage.StaticFilesStorage
,也就是文件系统,第一阶段介绍的那个。Django 的官方文档有一个如何使用 cloud 服务、CDN 的 guideline。如果你想自己自己写一个 storage backend,这个文档应该会对你有所帮助。
上图还包含了一个最佳实践:根据 DEBUG
选择不同的aws prefix,这样就不会把测试时的静态资源推到生产 aws bucket。
这时的 collectstatic
会把 STATICFILES_DIRS
的静态资源推到 aws(或其他 cloud provider),而之前的是本地的文件系统。
![817392fb9fe7ebc72be1c71b16e0f70d.png](https://i-blog.csdnimg.cn/blog_migrate/31321bf43a168514bd058dc672f8749c.jpeg)
你的 stroage engine会为你 handle 正确的 url,比如在模板页面里面使用 static
,能够正确指向实际的 url。
![61abc1a0ef066d8bff42988880c86373.png](https://i-blog.csdnimg.cn/blog_migrate/606450b493c193bd905e1f861a1b1cf1.jpeg)
总结一下这个阶段:
- 推荐使用
django-storages
,如果你有足够实力,可以按照 django 官方文档介绍的 API 自己写一个 storage engine。 - 关键设置为:
STATICFILES_STORAGE
。 - 再次:使用
static
,不要硬编码。 - 可以把
collectstaic
当作 CI一部分。
0x03 User-Uplaod Media
让用户上传文件到你的服务器是存在很多安全隐患的,所以最好使用第二步提到的 cloud provider。作者提到的是使用 django 的 model form 上传 media,这在某些情况下是做不到的,比如前后端分离的场景。前端使用 cloud provider 的sdk上传至cloud,然后把 url post 给后端或许更加常见。当然如果你使用到了 ImageField
或者 FileField
,有两个参数是你可以利用的: STATICFILES_STORAGE
和 DEFAULT_FILE_STORAGE
,当你设置为 aws 相关配置的时候,它能够自动为你上传到 aws。
![b0cf3377b538590991599713903ff2e3.png](https://i-blog.csdnimg.cn/blog_migrate/f4bc5066a1c78a4443124020f325175a.jpeg)
总结一下此阶段:
- 推荐使用
django-storages
。 - 关键配置参数:
DEFAULT_FILE_STORAGE
。 - 使用
ImageField
、FileField
的时候指定upload_to
。
Asset Compilation
也就是前后端分离,前端使用 webpack
、 react
or vue
技术栈。所以你需要:
- npm
- webpack
- webpack-bundle-tracker
- django-webapck-loader
webpack-bundle-tracker
和 django-webapck-loader
能减少你的 headache。简单来说, webpack-bundle-tracker
生成 metadata 数据, django-webapck-loader
利用 metadata 数据使其更好地和 django app 结合。
![e5c76896a025ebaa9d68dd2741af85c4.png](https://i-blog.csdnimg.cn/blog_migrate/c26c15bf04d258349f275ada0819b2a3.jpeg)
webpack
自己是一套完整的体系,你想要很复杂,足够你复杂的,但是简单的使用大致如下:注意最下面的 ./webpack-stats.json
文件,这是 webpack
和 django
连接的桥梁。
![40bd551ca8773e4d670dcc8cfb96df6a.png](https://i-blog.csdnimg.cn/blog_migrate/69249370617efd7d9b2708c4c5ee6a64.jpeg)
重要的配置如下:
![1e76f335cafb85cf9fd654f024a03fd4.png](https://i-blog.csdnimg.cn/blog_migrate/732123612b35300eef26cc3b4407579c.jpeg)
你只需要运行两条指令:
![ffcab4c757370c44848d5160d4069921.png](https://i-blog.csdnimg.cn/blog_migrate/ca8a4f2f2267f170cdb4a703c6e098d2.png)
collectstatic
知道如何通过 webpack-stats.json
找到 bundle 文件,然后把它推送到该去的位置:本地文件系统、aws...
![7290f8bf46141ca8871a9dd4e0e12ee2.png](https://i-blog.csdnimg.cn/blog_migrate/ef5e5dcb83573b4a0e8b9df278bd34df.jpeg)
总结一下此阶段:
- 推荐使用
webpack-bundle-tracker
和django-webapck-loader
。 - 关键配置项:
INSTALLED_APPS+="webpack"
,WEBPACK_LOADER={}
,webpack.config.js
。 - compile、存储静态资源分两步:
webpack
->collectstatic
。
![f41f6f4b7ec94290488314dd1e00ef3c.png](https://i-blog.csdnimg.cn/blog_migrate/21fd5cfa5d5c4d01e0467da9db2eccea.jpeg)
如果你像我一样真正热爱计算机科学,喜欢研究底层逻辑,欢迎关注我的微信公众号:
![0768693d6e72d4e700b83680cf755f5e.png](https://i-blog.csdnimg.cn/blog_migrate/9c59625210114af3adabde3dd62e43d9.jpeg)