本地开发使用 django 自带的服务器,静态文件直接在项目目录中托管。一旦要往生产环境部署时,就会发现必须为前端静态文件和其他媒体文件配置一个单独的存储后端,Django 说它不管这事儿。

存储后端可以直接在服务器上配置一个静态服务器,也可以直接使用 AWS S3 之类的对象存储,这里主要记录对象存储后端的配置方法。

对于 wagtail 来说,使用对象存储并不能让网站程序完全减负,很多对图片和文档的操作需要先将文件从对象存储取回到服务器的内存中,处理好以后再返回给访问者。Anyway,对象存储可以分担带宽,总之利大于弊。

第一步 安装存储管理相关的包

使用 django-storages 管理存储后端,使用 boto3 实现 s3-like 对象存储的管理。

$ pipenv install django-storages boto3

将包信息写入 requirements.txt 文件:

$ pip freeze > requirements.txt

第二步 启用 storages 模块

编辑 base.py,添加 storages 到应用列表:

INSTALLED_APPS = [
    ...
    'storages',
    ...

第三步 配置对象存储后端

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.2/howto/static-files/

STATICFILES_FINDERS = [
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
]

STATICFILES_DIRS = [
    os.path.join(PROJECT_DIR, 'static'),
]

STATIC_ROOT = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'


# Django-Storages
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
STATICFILES_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'

# 对象存储设置
AWS_ACCESS_KEY_ID = ''
AWS_SECRET_ACCESS_KEY = ''
AWS_STORAGE_BUCKET_NAME = ''
AWS_S3_ENDPOINT_URL = ''
AWS_S3_REGION_NAME = 'cn-shanghai'
AWS_S3_CUSTOM_DOMAIN = '%s.oss-%s.aliyuncs.com' % (AWS_STORAGE_BUCKET_NAME, AWS_S3_REGION_NAME)
AWS_S3_FILE_OVERWRITE = False
AWS_DEFAULT_ACL = None

特别注意:AWS_S3_ENDPOINT_URL 这个地址一定要带协议头,不然无法上传图片。比如:AWS_S3_ENDPOINT_URL = 'https://oss-cn-shenzhen.aliyuncs.com'

避免 Wagtail 管理界面 icons 不显示

由于对象存储默认不允许文件之间跨域请求,主要是 css 文件中如果引用了外部的图片做背景或实现 icon 这些情况,如果没有配置 CORS,Wagtail 管理界面的各种 icons 就不给你显示。

解决方法Wagtail 使用 s3 存储不显示 icon

另外,对象存储桶访问权限要配置成 公共读

重新归集静态文件

$ python manage.py collectstatic

执行命令后,本地的各路静态文件就会整齐的复制到配置的对象存储桶里面。