Static files get deployed from STATICFILES_DIRS, but not STATIC_ROOT - django

I have problems with deploying files in my development environment.
See my configuration below.
python manage.py collectstatic collects all files from '/Users/vikingosegundo/Projects/website/media/' as expected and stores them at /Users/vikingosegundo/Projects/website/mydjangoproject/static/.
But although the links to the css files are correct when using <link href="{% static "css/style.css"%}" rel="stylesheet" type="text/css"> (rendered as <link href="/staticmedia/css/style.css" rel="stylesheet" type="text/css">), the originals files at /Users/vikingosegundo/Projects/website/media/ will be deployed, not from the STATIC_ROOT /Users/vikingosegundo/Projects/website/mydjangoproject/static/.
Even if I delete the files that are in /Users/vikingosegundo/Projects/website/media/.
Where is my misconfiguration?
settings.py
MEDIA_ROOT = '/Users/vikingosegundo/Projects/website/mydjangoproject/media/'
MEDIA_URL = '/sitemedia/'
STATIC_ROOT = '/Users/vikingosegundo/Projects/website/mydjangoproject/static/'
STATIC_URL = '/staticmedia/'
STATICFILES_DIRS = [
'/Users/vikingosegundo/Projects/website/media/',
]
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)
TEMPLATE_CONTEXT_PROCESSORS = (
'django.contrib.auth.context_processors.auth',
'django.core.context_processors.debug',
'django.core.context_processors.i18n',
'django.core.context_processors.media',
'django.core.context_processors.static',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
#....
)

I think, this is because the serving of static files using the django build-in views and helpers is intended for development and debugging purposes only. When DEBUG is True in your project settings, your static files are served from their original location. This helps to avoid being forced to run the collectstatics management command every time you for example change your CSS files.
When you switch your DEBUG setting off, django.conf.urls.static.static and its cousins helpers will stop working, since they are intended for development purposes only. Still, the template tags will work, since they must point to the correct static file urls in either production or development.
Running the collectstatic management command is a convenient helper for copying your static files to their final destination (STATIC_URL), where serving them in a production environment is your own responsibility. This is best done by an (static) web server location (avoiding pumping them through the django/python process), and thus Django's docs explicitly recommend to not use Django for static file serving.
See Managing static files: Serving static files in development for more about serving static files in development.

Related

Local development Django static files coming from library directory rather than my project

I have a Django (3.1) app that I've set up to serve static files, that is, myapp/settings.py has
DEBUG = True
.
.
.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'myapp',
.
.
.
]
.
.
.
STATIC_URL = '/static/'
STATIC_ROOT = 'static/'
But instead of serving files from the static directory of myapp, it's serving static files from /Library/Python/3.7/site-packages/django/contrib/admin/static/. I have tested this by adding files to both directories,
~/Projects/myapp/static/file-from-project.js
/Library/Python/3.7/site-packages/django/contrib/admin/static/file-from-library.js
and then
python3 manage.py runserver
with a template including the lines
<script src="{% static 'file-from-project.js' %}"></script>
<script src="{% static 'file-from-library.js' %}"></script>
and file-from-library.js loads fine but I get a 404 for file-from-project.js. What am I doing wrong here?
Directory structure with the referenced files:
myapp
/myapp
settings.py
.
.
.
/static
file-from-project.js
.
.
.
/templates
.
.
.
manage.py
.
.
.
OK, I see the problem I think.
STATIC_ROOT is an absolute path, not a relative one. if you set it to eg. BASE_DIR / "static" you might get what you want.
I usually set BASE_DIR at the top of my settings.py as it gets used for a few things:
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent
The other thing is that you have DEBUG=True which means it's going to be looking at your STATIC_URL under your app dirs. If you move the file to:
~/Projects/myapp/static/app_folder/file-from-project.js
It should work :)
Edit: I noticed myapp is an app, and not the project name, which makes me wonder what the project is called.
Your static files for development for this structure should probably be in:
~/Projects/myapp/static/myapp/<static file>
When you deploy, obviously DEBUG should be False, but here you should run collectstatic in order to gather all the static files in one place for deployment.

Static files not working with Django, Heroku, and Django Sass Processor

I can't seem to get static files to work when deploying to Heroku. I get 404s for all css and js files.
Things I'm using:
Django 2.1.5
whitenoise 4.1.2
django-sass-processor 0.7.2
django-webpack-loader 0.6.0
Here are my settings:
Whitenoise is in the middleware
MIDDLEWARE = [
'django.middleware.gzip.GZipMiddleware',
'django.middleware.security.SecurityMiddleware',
'whitenoise.middleware.WhiteNoiseMiddleware',
'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'
]
All of the static file settings:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles/')
STATIC_SOURCE_ROOT = os.path.join(BASE_DIR, 'static/')
STATICFILES_DIRS = [
STATIC_SOURCE_ROOT
]
STATICFILES_STORAGE = 'whitenoise.storage.CompressedStaticFilesStorage'
STATICFILES_FINDERS = [
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'sass_processor.finders.CssFinder'
]
# Ensure STATIC_ROOT exists.
os.makedirs(STATIC_ROOT, exist_ok=True)
"""
Django Sass Processor
https://github.com/jrief/django-sass-processor
Template Usage:
{% load sass_tags %}
<link href="{% sass_src 'myapp/css/mystyle.scss' %}" rel="stylesheet" type="text/css" />
"""
SASS_PROCESSOR_INCLUDE_DIRS = [
os.path.join(STATIC_SOURCE_ROOT, 'scss/')
]
SASS_PROCESSOR_ROOT = STATIC_ROOT
SASS_PROCESSOR_ENABLED = False
# Django Webpack Loader
# https://github.com/owais/django-webpack-loader
WEBPACK_LOADER = {
'DEFAULT': {
'BUNDLE_DIR_NAME': 'dist/',
'STATS_FILE': os.path.join(BASE_DIR, 'webpack-stats-prod.json')
}
}
DEBUG = False
When I go to deploy I follow these steps:
Run yarn run build
Which builds the js (I'm using React so there is babel and such) and places it into 'static/dist/' - which gets committed to git
Deploy to Heroku
I have collectstatic disabled on heroku so it doesn't get called automatically on deploy
Run on Heroku: heroku run python manage.py compilescss
Which I believe should compile the scss into css and places the css files next to the scss files in 'static/'
Run on Heroku: heroku run python manage.py collectstatic --ignore=*.scss
Which I believe should copy everything (except .scss) from 'static/' to 'staticfiles/'. This should be all of the compiled css files and the compiled js.
I've played with a lot of settings but nothing seems to work, the css and js get a 404.
Any ideas?
I haven't used this exact set of tools before, but I think you'll have better luck if you approach things this way:
Make sure your application is configured to run two buildpacks. heroku/nodejs should run first and heroku/python should run second.
Since you're manually running yarn now I suspect that this is already done. yarn isn't included in the Python buildpack.
Add a heroku-postbuild script to your package.json that runs yarn build. This should cause your React code to get built during deployment after your Node.js dependencies have been installed.
Re-enable Heroku's automatic collectstatic by running heroku config:unset DISABLE_COLLECTSTATIC. I don't think you actually need to ignore the .scss files.
You might also want to take a look at django-heroku, a Django library from Heroku that helps set up deployment on their platform. It's officially recommended and may well help resolve your HTTP 404 issues.

Django staticfiles with cache busting

I'm trying to migrate my project from using {% compress %} to grunt for the whole front-end workflow. I got my grunt setup correctly and I can generate my main.min.css and main.min.js. With collectstatic I see them copied to the right folder, but when I deploy to staging all I get is a big fat 500 error.
INSTALLED_APPS = (
'django.contrib.contenttypes',
'django.contrib.messages',
'django.contrib.staticfiles',
'captcha',
'core',
)
STATICFILES_STORAGE = 'django.contrib.staticfiles.storage.ManifestStaticFilesStorage'
STATICFILES_FINDERS = (
"django.contrib.staticfiles.finders.FileSystemFinder",
"django.contrib.staticfiles.finders.AppDirectoriesFinder",
"compressor.finders.CompressorFinder",
)
and in the template:
<link rel="stylesheet" href="{% static "core/dist/css/main.min.css" %}" />
It works locally if I set DEBUG=False in settings.py (without loading the static files obviously). Any idea?
For everyone ending up here in the future: check your .gitignore file and be sure to only reference existing files in the template!
In my case I had dist/ in my .gitignore and I was storing my static files in core/dist/ so they got gitignored and ended up not being on the server.

Django runserver not serving some static files

My local testing server for Django v1.8.2 on Windows 8.1 is only serving certain static files. Others are giving a 404 error.
#urls.py - excerpt
urlpatterns = [
url(r'^$', views.index)
] + staticfiles_urlpatterns()
#settings.py - excerpt
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'main',
'users'
)
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static/")
As far as I can tell the development server is configured to serve static files. When running runserver I get no warnings, and my code displays no syntax errors (import statements do exist and so forth). I did for testing purposes run collectstatic before starting the server just to be sure at least once.
My view template is:
{% load staticfiles %}
<img src="{% static 'main/img/ComingSoon.jpg' %}" alt="Coming Soon">
The link generated is /static/main/img/ComingSoon.jpg which looks correct, the file does exist in that location. What perplexes me is that this directory produces a 404 error, but other static files are served. The directory hierarchy is:
static/
admin/
css/
..
js/
..
img/
..
main/
img/
ComingSoon.jpg
The URL localhost:8000/static/admin/img/ gives an expected message about indexes being not allowed. However, localhost:8000/static/main/img/ reports \main\img\ cannot be found. Both are 404 statuses. Images within static/admin/img/ do display correctly with the same links as what is giving an error. The Administration site for Django does display correctly.
Why would one directory within static/ not be indexed or accessible?
According to the Django documentation regarding static/:
This should be an initially empty destination directory for collecting
your static files from their permanent locations into one directory
for ease of deployment; it is not a place to store your static files
permanently. You should do that in directories that will be found by
staticfiles’s finders, which by default, are 'static/' app
sub-directories and any directories you include in STATICFILES_DIRS).
I moved the files to another directory such as:
myApp/
main/
static/
main/
img/
..
static/
..
After running collectstatic I noticed the script created the subdirectories in myApp/static/ as expected and it must have generated the URLs needed because it now properly serves the files.

Azure local emulator does not serve django static files correctly

I have followed the Django / Visual Studio / Azure tutorial http://www.windowsazure.com/en-us/develop/python/tutorials/django-with-visual-studio/. I have a very simple application, basically one simple html template with one javascript and one css file (code examples at the end).
When I run the code in the local debugger, everything works fine. When I try to run the code in the local Azure emulator with default VS and Azure SDK provided settings, I get the html file as response for both the javascript and css requests. For example, request for /static/calculator.js returns the application's html template instead of calculator.js.
What could cause this behavior and how could this be fixed?
UPDATE:
It seems that as I run the website in Azure emulator, any url on the emulator host 127.0.0.2 will return the "main page", that is, the only view defined in views.py. For example, 127.0.0.2/ returns the webpage (as it should), and so does 127.0.0.2/nonexistenturl. My hunch is that this is somehow due to misconfiguration of either fastcgi or IIS express as used by Azure emulator. What would be good starting points for trying to fix this problem?
Code examples:
Html template links:
<link rel="stylesheet" type="text/css" href="/static/calculator.css">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript" src="/static/calculator.js"></script>
urls.py:
urlpatterns = patterns('',
url(r'^$', 'ExamCalculator.Calculator.views.main_page'),
)
in settings.py staticfiles related settings should be correct:
STATIC_ROOT = 'C:/.../static/'
STATIC_URL = '/static/'
# Additional locations of static files
STATICFILES_DIRS = (
# Put strings here, like "/home/html/static" or "C:/www/django/static".
# Always use forward slashes, even on Windows.
# Don't forget to use absolute paths, not relative paths.
)
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
...
)