Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Serving root-level static files on Heroku with Django?

I need to serve several root-level static files on Heroku (eg, domain.com/favicon.ico). Here's the list of files as it currently stands:

favicon.ico
crossdomain.xml
sitemap.xml
robots.txt
humans.txt
apple-touch-icon-57x57-precomposed.png
apple-touch-icon-57x57.png
apple-touch-icon-72x72-precomposed.png
apple-touch-icon-72x72.png
apple-touch-icon-114x114-precomposed.png
apple-touch-icon-114x114.png
apple-touch-icon-precomposed.png
apple-touch-icon.png

I've searched high and low and can't find a standard way to serve a large set of static files. Wherever I host them (on Heroku with collectstatic or Amazon S3), explicitly defining and redirecting 14 files in my urls.py seems incorrect.

like image 380
knite Avatar asked Jul 21 '12 03:07

knite


2 Answers

This is my current solution. Feedback appreciated.

from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from settings import STATIC_URL, ASSETS, DEBUG, AWS_STORAGE

#ASSETS is a tuple: ('favicon.ico, 'robots.txt', ...)    
urls = [('^%s$' % f, 'redirect_to', {'url': STATIC_URL + f}) for f in ASSETS]
urlpatterns += patterns('django.views.generic.simple', *urls)

#Serve static files from runserver if in dev mode with S3 off.
if DEBUG and not AWS_STORAGE:
    urlpatterns += staticfiles_urlpatterns()
like image 196
knite Avatar answered Oct 04 '22 00:10

knite


Despite this is being an old question, I still have the problem. I like the way the URLs are generated from a list in the current solution, but I was not convinced that was the best.

After a bit of research though, I found realfavicongenerator.net being a very useful resources which generates all the required favicons files for you and I was sent this post by a colleague which seems to support the proposed solution, with a more recent Django version.

Based on all the above, my solution is using native sitemap framework, django-robots for robots.txt and a ROOT_ASSETS dictionary, with files prefix as key, and values as a list of files, for example:

ROOT_ASSETS = {
    "images/favicons/": [
        "apple-touch-icon-114x114.png",
        "apple-touch-icon-120x120.png",
        "apple-touch-icon-144x144.png",
        "apple-touch-icon-152x152.png",
        "apple-touch-icon-180x180.png",
        "apple-touch-icon-57x57.png",
        "apple-touch-icon-60x60.png",
        "apple-touch-icon-72x72.png",
        "apple-touch-icon-76x76.png",
        "apple-touch-icon-precomposed.png",
        "favicon.ico",
    ]
}

Then I generate my urls with:

from django.conf.urls import patterns, url, include
from django.contrib.staticfiles.storage import staticfiles_storage

root_assets_urls = []
for prefix, files in ROOT_ASSETS.iteritems():
    for f in files:
        asset_url = staticfiles_storage.url("{prefix}{file}".format(prefix=prefix, file=f))
        root_assets_urls.append(
            url(r'^{0}$'.format(f), RedirectView.as_view(url=asset_url))
        )
root_assets = patterns('', *root_assets_urls)

urlpatterns = patterns(
    '',
    url(r'^', include(root_assets)),
    [...]
)

I'm also including the HTML generated by realfavicongenerator.net in my master template's head.

like image 2
Bruno A. Avatar answered Oct 04 '22 01:10

Bruno A.