Django on Heroku -- static files not being found - django

I am running Django on Heroku. I can successfully run collectstatic, but when I go to the site it is obvious that Django is unable to find my static files. Here's a snippet from my settings -- I think it's mostly standard stuff:
STATIC_ROOT = ''
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'
PROJECT_DIR = os.path.abspath(os.path.dirname(__file__))
# 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.
os.path.join(PROJECT_DIR, 'static'),
)
# List of finder classes that know how to find static files in
# various locations.
if CLAYS_ENV == 'dev':
STATICFILES_FINDERS = (
'django.contrib.staticfiles.finders.FileSystemFinder',
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
'django.contrib.staticfiles.finders.DefaultStorageFinder',
)
And in my case the CLAYS_ENV variable will be set to 'dev'. Any ideas on why Django can successfully run collectstatic, but then can't find the files afterwards?

Collect static and serving static media are two different things. Collectstatic just puts your static media in your STATIC_DIRS
Serving your static files is a process of the server not the collectstatic command. Ive never deployed to heroku before but do you have a url to map your static assets to their location?
if not settings.DEBUG:
urlpatterns += patterns('',
(r'^static/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
Which server are you using? Usually you want the server to serve static media, though, instead of django. In apache this is done by setting up an Alias

It's recommended to serve static files through a CDN (like Amazon S3) when using Heroku. While you can still manage to serve those directly from Heroku, the same process attending dynamic requests is also serving static data, wasting processing time. Also, in case of media files, the use of a CDN is mandatory, since Heroku's file-system is "ephimeral": Every time you deploy new code, a new image of the Cedar stack is recreated from scratch and a new code checkout is made. Every file not Git-tracked created between deploys is lost.

Related

Why Django 4.0 can access static files only with STATICFILES_DIRS, not STATIC_ROOT

When I use STATIC_ROOT:
STATIC_ROOT = BASE_DIR / 'static'
Django cannot access static files and always return 404 error for them.
But when I use STATICFILES_DIRS:
STATICFILES_DIRS = [
BASE_DIR / "static",
]
Everything works well. What's the issue?
I don't understand why Django works in this way, I always thought that STATIC_ROOT is correct way of creating route.
STATIC_ROOT is where the collectstatic command will copy all the static files in.
This folder is meant for production use. So that all the static files in your project (from your apps, or third party apps etc.) are kept in a single folder and therefore becomes easy to serve in production.
By default, Django automatically searches for static files inside each app directory (this is helpful in writing reusable apps). The STATICFILES_DIRS setting allows you to define extra places to look for the static files.
Also, the STATIC_ROOT folder and the STATICFILES_DIRS folder should not be the same values.

Django serve files from STATIC_ROOT and use AppDirectoriesFinder at same time

I'm trying and failing to figure out a config for serving static files that works for me under these requirements:
I want the collectstatic command to work always (when Debug=True, and Debug=False), and to collect app dir statics. This implies I need both 'django.contrib.staticfiles' in INSTALLED_APPS and 'django.contrib.staticfiles.finders.AppDirectoriesFinder' in STATICFILES_FINDERS.
I want to serve some files out of STATIC_ROOT with Debug=True (Debug=False I want to serve all files out of STATIC_ROOT), that don't belong to any particular app. I just do.
I want the dev server (./manage.py runserver) AppDirectoriesFinder lookups to work when Debug=True.
As a compromise I could live with all static files out of STATIC_ROOT, but I still need Debug=True and collectstatic to work.
But I can't figure out how to do this.
I can't add STATIC_ROOT to STATICFILES_DIRS (not allowed)
Adding urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) to urls as suggested here does seem to not work in Debug=True with the dev server because the dev server overrides it and uses static finders.
Any ideas?

Django 1.8 Not Serving Static Files in Development

I am using the exact settings as in https://docs.djangoproject.com/en/dev/howto/static-files/ and my app is not loading the files. I've spent way to long trying to solve something so trivial but it's just not working. I've looked at alternatives, but these didn't work either.
This is in my setting file:
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, "static")
This is at the end my urls file:
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
I did a collect static when I had the static file dirs so there should be the correct files in my static dir. I also created test files and nothing.
Heres what it will say in the debug view:
Request Method: GET
Request URL: http://localhost:8000/static/assets/stylesheets/style.css
Raised by: django.views.static.serve
Last time I wrote an app this worked fine, i'm not sure why is isn't now.
You haven't used the exact settings in the docs...Which is fine, but you need to at least do the following, if DEBUG = False:
Set up STATICFILES_DIRS. This should be the absolute path to the folder where your static assets live (before they're "collected").
Set up STATIC_ROOT. This is different than the above path, and is where all of your static assets will be collected when you run collectstatic.
Run the collectstatic command to collect (i.e. copy) your assets from your STATICFILES_DIRS to your STATIC_ROOT
Depending on your configuration, and if DEBUG = True, you don't even need to define STATIC_ROOT in development mode.

Setting up django static directory for testing/development

In production, the apache server can handle serving static files just fine. For testing on my local machine I'm using manage.py runserver.
It seems the django apps I have somehow inject some default search paths into this debug server. The browser url shows everything under /static/whatever, but those files are coming from all over the place. This is fine for testing but when moving to production I'll need them in the one path. Thankfully, manage.py collectstatic provides a handy method to copy everything to the one directory given by STATIC_ROOT in settings.py. I've set mine to os.path.join(BASE_DIR, 'static/') where BASE_DIR is where manage.py is.
Now I want to start adding my own stuff in static, but everything's still being hosted by these hidden search directories provided by apps under DEBUG=True. I've tried the following in urls.py:
from django.conf import settings
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()
and
import re
from django.conf import settings
if settings.DEBUG:
static_url = re.escape(settings.STATIC_URL.lstrip('/'))
urlpatterns += patterns('',
(r'^%s(?P<path>.*)$' % static_url, 'django.views.static.serve', {'document_root': settings.STATIC_ROOT}),
)
Neither have worked.
I tried providing my static directory in STATICFILES_DIRS, but get the error ImproperlyConfigured: The STATICFILES_DIRS setting should not contain the STATIC_ROOT setting. So then I tried removing my STATIC_ROOT so the path was only given in STATICFILES_DIRS. Finally I can access my files in development (still with staticfiles_urlpatterns from above).
However, I'm pretty sure removing STATIC_ROOT is not the right way to go about it. For a start, I won't be able to run collectstatic after installing other apps without manually changing everything around again. How should I be configuring my static directory for development?
Also, is there a way to turn off hosting app specific static directories so I can make sure my single static is set up correctly (but still be in development mode)?
You're making this more complex than it needs to be. Include "static" in STATICFILES_DIRS as you are doing, for the project-level assets, but make STATIC_ROOT - ie the destination of the collectstatic command - something else, probably "staticfiles", and alias that directory to /static/ in Apache. Django will serve your assets from STATICFILES_DIRS automatically, without you even needing to add the urlpatterns.
OK, I completely missed the point here.
STATIC_ROOT is for collectstatic to pool all the static content for you. You don't add your files to here because it gets overwritten.
Now for production you can get your webserver to host the directory STATIC_ROOT and point STATIC_URL to the url it can be found through the webserver.
STATICFILES_DIRS allows you to add your own directories for collectstatic to search and pool to STATIC_ROOT. Then you can nicely separate static stuff for each of your apps and/or a common project static.
For dev, django expects everything to be in STATICFILES_DIRS and hosts that, not STATIC_ROOT because then there would be duplicates. This makes sense for larger projects because you want to be working on the per-app files, not some blob of stuff for a website.

Django Static Files Development

This seems to be a source of much confusion judging by the amount of similar titles on the subject, however trying everything I could find on static files with the django development server I've almost given up hope!
So my static files are served from C:/Users/Dan/seminarWebsite/static/, in which I have sub folders for images, css etc.
SETTINGS:
STATIC_ROOT = 'C:/Users/Dan/seminarWebsite/static/'
STATIC_URL = '/static/'
The static files app is also active.
URLS:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
TEMPLATE:
"{{ STATIC_URL }}images/vision.jpeg"
However only a broken link appears and at this address: http://127.0.0.1:8000/homepage/images/vision.jpeg and I don't think it should be at that address (homepage is the url name of the page the static image file is being called to).
Based on what you've posted so far, it looks like you're following the docs for django.contrib.staticfiles. I agree that the docs can be difficult to follow especially if one is new to django.
I believe the confusion stems from the fact that django.contrib.staticfiles has two modes of operation:
During the development phase where the development server is used, it dynamically searches for static files in predefined directories and make it available on STATIC_URL
For deployment, it assists in collating static files to a single directory (defined using STATIC_ROOT) so that the static files can be hosted using a webserver suited for static files. This collation is done using python ./manage.py collectstatic.
Here's a quick summary of how to get up and running. I haven't had a chance to try it out so there may be mistakes. Hopefully this will help you get started and at the very least help you understand the docs. When in doubt, do refer to the docs.
Hosting static files on the development server
Make sure you have 'django.contrib.staticfiles' in INSTALLED_APPS
Specify STATIC_URL. This will be the path where your static files will be hosted on.
STATIC_URL = '/static/'
Make sure your files are in the correct directories. By default, staticfiles will look for files within the static/ directory of each installed app, as well as in directories defined in STATICFILES_DIRS. (This behaviour depends on backends listed in STATICFILES_FINDERS).
In your case, you'd probably want to specify your directory in STATICFILES_DIRS:
STATICFILES_DIRS = (
'C:/Users/Dan/seminarWebsite/static/',
)
Make the view accessible by adding the following to the end of urls.py:
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()
Make sure you have DEBUG = True in settings.py.
That's it.
If you run your dev server (./manage.py runserver), you should be able to access your file via http://localhost:8000/static/images/vision.jpeg (which serves C:/Users/Dan/seminarWebsite/static/images/vision/jpeg).
Linking to static files in your templates
There are two ways to get a correct link for your static files - using the staticfiles template tag, and making STATIC_URL accessible to your templates. Since you've attempted the latter, we'll stick to that.
Make sure you have 'django.core.context_processors.static' in TEMPLATE_CONTEXT_PROCESSORS. If you haven't redefined TEMPLATE_CONTEXT_PROCESSORS then there is nothing to do since it should be there by default.
Make sure you use RequestContext when rendering your template. Example:
from django.template import RequestContext
# ...
def some_view(request):
# ...
return render_to_response('my_template.html', {
"foo" : "bar", # other context
}, context_instance = RequestContext(request))
You should now be able to use the following in your my_template.html:
<a href="{{ STATIC_URL }}images/vision.jpeg" />
Hosting static files on production server.
If all the static files you need to serve are store in that one directory (C:/Users/Dan/seminarWebsite/static), then you're almost there. Simple configure your webserver to host that directory on /static/ (or whatever you set STATIC_URL to) and you're good to go.
If you have files scattered in different directories and/or app specific static files, then you'll need to collate them.
Set STATIC_ROOT to the directory where you want to store the collated files.
Run ./manage.py collectstatic to do the collation.
Configure your webserver to host the that directory (STATIC_ROOT) on /static/ (or whatever you set STATIC_URL to).