in production, django {% static 'file/path' %} command looks for the file path on Herokuapp when it should be looking through Cloudinary

82 views Asked by At

Static files are not working in production.

summary of problem areas

Cloudinary and Django settings.py and templates are set up correctly after rigourous scrutiny and peer comparison.

inspecting the media library on Cloudinary, everything updates correctly from the project and can be viewed. Another way to look at is with this table.

production stage result
Django project sending static files to Cloudinary's media library working exactly as expected
Django deploying to Heroku working exactly as expected (other than Cloudinary)
Cloudinary serving static files to Heroku not working as expected, page source indicates confusion with herokuapp and cloudinary.

debugging steps

compare page sources on localhost vs production

  <link rel="stylesheet" href="{% static 'css/style.css' %}">

in localhost this directs succesfully to the static file localhost:8000/static/css/style.css

in production, here's where we run into trouble. There is no CSS and the same line of code reads as:

   <link rel="stylesheet" href="[/static/css/style.css](https://coach-matrix-d2cd1e717f81.herokuapp.com/static/css/style.css)"> <!-- this is a 404 empty link, should loads static files from cloudinary, not herokuapp, should lead to an URL like https://res.cloudinary.com/dh1xovduy/raw/upload/v1703781479/static/css/style.674a1e0f7f03.css -->

when I inspect the page source of my peer's open source project that is is working, it works perfectly.

localhost:

    <link rel="stylesheet" href="{% static 'css/style.css' %}">

in production:

    <link rel="stylesheet" href="https://res.cloudinary.com/ksjl86/raw/upload/v1/static/css/style.574ae5e833b9.css">

although I'm also having this issue with django-quill-editor, I am now inspecting CSS as may be easier to solve. I had a temporary working solution of linking directly to the entire cloudinary URL , but have now redacted so I can inspect the page source further

The only temporary workaround to get css displaying successfully is below

<link rel="stylesheet" href="https://res.cloudinary.com/dh1xovduy/raw/upload/v1703781479/static/css/style.674a1e0f7f03.css"> <!--linking directly to the file and now works successfully-->

however this solution is not ideal as it still leaves problems with other static files such as django-quill.

With django_quill I also have the issue with a faulty file path being requested on Herokuapp not cloudinary.

debugging steps

as noted earlier, django settings.py STATIC_ROOT etc are all working correctly as has been reviewed by several peers, it should not require further review. It also uploads correctly using collectstatic. The issue must surely be between Cloudinary and Heroku.

inspect heroku config vars, use DISABLE_COLLECTSTATIC=0

Setup, as far as I can tell, is correct see below [with Redacted credentials.]

CLOUDINARY_URL=cloudinary: [REDACTED URL IS HERE]

DATABASE_URL=postgres: // [REDACTED URL HERE]

DISABLE_COLLECTSTATIC=0

PORT=8000

SECRET_KEY= [REDACTED KEY IS HERE]

inspect settings.py

From everything I've read up in documentation this is the correct setup. I've also consulted with a peers open-source repository who has their's working correctly, however we will see in next section that theirs does successfully link to herok.

my settings.py is formatted exactly the same as that of my peers in regards to cloudinary setup. for elegance and readability I will retract full code exerpt but instead provide link to my settings.py here.

I have full conviction that my settings.py is working correctly.

inspect deployment log in heroku and procfile

Procfile reads as

web: gunicorn coachmatrix.wsgi
release: python manage.py collectstatic --noinput

as expected, Heroku subsequently acknowledges the static files from cloudinary, 0 static files copied, 1386 post-processed.

update tuples

try change line 192 in settings.py from STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')] to STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),) this being a tuple and having the comma is important

add variables from env.py

I'm sure that the config vars in Heroku is causing a problem. I've tried entering these details with correct key in the second column (hidden here from view) All of these lead to same issue as described.

version 0

 CLOUDINARY_URL 
DATABASE_URL
DISABLE_COLLECTSTATIC PORT SECRET_KEY

version 1

CLOUDINARY_API_KEY
CLOUDINARY_API_SECRET
CLOUDINARY_CLOUD_NAME
CLOUDINARY_URL
DATABASE_URL
DISABLE_COLLECTSTATIC
PORT
SECRET_KEY

version 2

CLOUDINARY_API_KEY
CLOUDINARY_API_SECRET
CLOUDINARY_CLOUD_NAME
CLOUDINARY_URL
DATABASE_URL
PORT
SECRET_KEY

version 3

CLOUDINARY_API_KEY
CLOUDINARY_API_SECRET
CLOUDINARY_CLOUD_NAME
DATABASE_URL
PORT
SECRET_KEY
1

There are 1 answers

0
Laurie Crean On

It emerged that the issue was related to a lack of Whitenoise middleware, which is a python package that is specifically good for simplifying staticfiles and letting them be served within the deployed webapp.

Despite initial concerns, Cloudinary or Heroku were therefore working well all along and could instead be fixed internally within the code repository with a very simple solution.

Here's how it was fixed.

  • pip install whitenoise in terminal
  • add whitenoise==6.6.0 to requirements.txt
  • in settings.py update Middleware
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'whitenoise.middleware.WhiteNoiseMiddleware', # added whitenoise middleware here.
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'allauth.account.middleware.AccountMiddleware',
]

Credit to Sean Mead from the Code Institute Alumni community for finding this final piece in the puzzle.