Search code examples
djangowagtaildjango-storage

Wagtail CMS documents returning 404


I've got a Wagtail CMS site (running 1.13.1). It sits on two servers behind a load balancer and is using S3 for static and media assets which is managed by Django Storages.

When I add a document to a page in the CMS, the document is uploaded to S3 but both the admin and the template can't find the document and return an error saying:

ClientError: An error occurred (404) when calling the HeadObject operation: Not Found

In the template I'm out putting the document's url using {{ item.url } (It I use item.file.url it works fine because it uses the CDN url.)

In the 'documents' section of the CMS admin I'm getting an error saying: "The file could not be found. Please change the source or delete the document"

I'm pretty baffled by it. To make matters worse, it does eventually show up.

The document is accessible via both the S3 url and the CloudFront url but wagtail uses its own url. ie: https://mywebsite.com/documents/20/mypdffile.pdf rather than https://cloudfront.url/media/documents/mypdffile.pdf

Config file highlights include:

STATIC_URL = 'https://cloudfront.url/static/'
STATICFILES_LOCATION = 'static'
STATICFILES_STORAGE = 'project.custom_storages.StaticStorage'

MEDIA_URL = 'https://cloudfront.url/media/'
MEDIAFILES_LOCATION = 'media'
DEFAULT_FILE_STORAGE = 'project.custom_storages.MediaStorage'


AWS_STORAGE_BUCKET_NAME = 's3bucket.url'
AWS_S3_REGION_NAME = 'ap-southeast-2'
AWS_ACCESS_KEY_ID = 'ACCESS KEY'
AWS_SECRET_ACCESS_KEY = 'SECRET ACCESS KEY'
AWS_S3_SECURE_URLS = True
AWS_IS_GZIPPED = True

AWS_S3_OBJECT_PARAMETERS = {
    'CacheControl': 'max-age=2592000',
}

AWS_S3_CUSTOM_DOMAIN = 'https://cloudfront.url/'
AWS_PRELOAD_METADATA = True

In my 'global' urls.py file I have:

urlpatterns = [
    url(r'', include(wagtail_urls)),

] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

As I say, static files and non-documents seem to show up fine.


Solution

  • The + static ... is for the development server only.

    See the docs:

    This helper function works only in debug mode and only if the given prefix is local (e.g. /media/) and not a URL (e.g. media.example.com).

    You can make these kinds of development urls explicitly conditional by wrapping it in if settings.DEBUG statement. Eg:

    if settings.DEBUG:
        urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)