Static Files in Django

So if you’ve read my earlier post, you’ll know that I’ve had problems with my static files before. But I thought my troubles were over. Then today, I decided to add a few things to my Django blog project, went into the admin to test some stuff and there was no CSS! My blog itself still had the CSS I wrote, but the admin had none. I then went and quickly looked at the live version, but that was fine. I’m honestly not sure what I’ve done that could have affected the admin CSS not showing, but I guess it was something. So, it was Google time!

I first browsed a few Stack Overflow posts, but none were particularly helpful. I usually find all kinds of useful information there, but it wasn’t working out for me today. Then I found this: Django Static Files.

I’d read about the collectstatic command before but not in any context that made it seem like it would help me. But it explains a lot.

So I ran this from my project folder:

manage.py collectstatic

I was informed that this would overwrite existing files but I have version control so I said ‘yes’! Of course, it didn’t really overwrite my files anyway since it was just adding Django’s admin folder. This solved my problem, but I was still curious about what exactly I was missing about static files to begin with.

I read Django’s official documentation on the matter here: https://docs.djangoproject.com/en/2.2/howto/static-files/

I thought I looked at that when I was having trouble with uploading my static files to Heroku, and maybe I did, but didn’t know enough to understand what I was reading, or something. It happens.

So I tried to adjust my static file situation to follow Django’s instructions. I’d originally had my static folder within my ‘blog’ folder, ‘blog’ being a Django app. That was how Django Girls had me set it up. I guess if I’d run collectstatic it would have put those folders in a static folder in my main directory, so that Heroku would have seen it. I’d ended up making that folder manually in order for my deployment to work. But Django Girls never mentioned using collectstatic. They also had you putting your CSS folder directly in the static folder, while Django recommends using appname/static/appname/css/style.css so that if you have multiple apps with static folders, and some have CSS files of the same name, you won’t run into the problem of only one of them working. So I adjusted my folder structure accordingly.

I then ran collectstatic again, and my newly created blog/static/blog/ folder with all my blog app’s static files was added to the base static folder. I deleted my manually added files, which were in the static/css folder. This broke my CSS but I was expecting that. I had to go to my style declaration to specify that my CSS file was now in blog/css/. This is what that line looks like now:

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

I then edited my Procfile so that Heroku would run collectstatic:

web: python manage.py collectstatic --noinput; gunicorn myblogsite.wsgi --log-file -

Now was the real test – deployment! I was scared. But it worked, sort of. Heroku did indeed appear to collect a bunch of static files, and my live site wasn’t completely broken. But it didn’t have CSS. Only the admin side did.

I found out that I can access my files on Heroku by going to the terminal and running:

heroku run bash
ls
cd static

The first line is to connect, the second line will list all files in the base directory, and the third changes to my static file directory. If you’re reading this I’ll assume you have at least a basic understanding of how to use the terminal and leave the explanation at that.

My project files such as manage.py were there in the base directory, as well as my static folder. I went there and checked it out and sure enough, the only folder that was inside was the admin folder. So for whatever reason, my blog files weren’t being collected even though they were when I ran collectstatic on my local project. I even double checked by deleting all the collected files from my blog app and rerunning the command. Yep, they got created. So why doesn’t it work on Heroku?

So it turns out I’m dumb. I had gone and added my static folder to .gitignore now that I knew I was supposed to be building that folder on my server (and it was in the original .gitignore file that Django Girls had me create). But I’d written ‘static/’ as opposed to ‘/static/’ so that was making it ignore all static folders in my project, instead of just the static folder in my project directory root. So Heroku didn’t have my blog/static files at all. When I changed it to ‘/static/’ my blog folder’s static files were uploaded properly so Heroku was able to find them when it collected my static files. And then, yay, CSS on my live website!

Apparently Heroku is supposed to run collectstatic without having to tell it to, but I’m done messing with it for the moment. I’d like to get some real updates on my project so I want to try not to break anything else today. Well, at least not anything else involving static files.

Key takeaways from this experience:

  • Read the docs! I need to get better at that. Honestly, especially when I was just starting, I often found the docs confused me more than they helped. But now I’m starting to understand them better and I realize just how important it can be to read them properly.
  • Double-check your .gitignore. Additionally, your code editor may have a simple way to see which folders and files are ignored. I use Visual Studio Code, and all my ignored stuff is grayed out in my file explorer.
  • Make sure you know what tools are available to you for debugging. It was a big help to me knowing how I could access my Heroku files, so that I could see for sure that my static files just didn’t exist there.