Simple way to set up Django and a SPA frontend on Heroku

This post was adapted from my Stack Overflow answer to a question about using single page applications (SPAs) with Django on Heroku.

Here’s how to set up Django to serve your static files and index.html on / while still having the possibility to use Django views for the admin dashboard, registration etc.:

from django.conf.urls import include, url
from django.contrib import admin
from django.contrib.staticfiles.views import serve
from django.views.generic import RedirectView

admin.autodiscover()

urlpatterns = [

    # / routes to index.html
    url(r'^$', serve,
        kwargs={'path': 'index.html'}),

    # static files (*.css, *.js, *.jpg etc.) served on /
    url(r'^(?!/static/.*)(?P<path>.*\..*)$',
        RedirectView.as_view(url='/static/%(path)s', permanent=False)),

    # other views still work too
    url(r'^admin/', include(admin.site.urls)),
]

I specify urlpatterns as a list, as Django 1.10 requires. The redirects are not permanent by default since 1.9, so you need to explicitly set permanent=True if you want browsers to cache this, though when debugging I find it better to start with False.

This approach allows you to use something like create-react-app or Yeoman frontend generators that package a built, minified frontend app into a single folder (like dist/). You then e.g. use a script to move that into Django’s static files folder (e.g. myproject/static/) and serve it from Heroku.

What many people say about wanting to use something like S3 for your static files stands, but sometimes you just want to start simple with one repository, one Heroku dyno and still be able to use Django + a SPA. Also, using something like WhiteNoise makes serving static files from Python pretty OK and allows you to
later on easily put a CDN in front of your static files.

Note: for user-uploaded files you should still use an outside service like Amazon S3 or Backblaze B2 (which is 4 lines of code to integrate).

Serving Media Files

WhiteNoise is not suitable for serving user-uploaded “media” files. For one thing, as described above, it only checks for static files at startup and so files added after the app starts won’t be seen. More importantly though, serving user-uploaded files from the same domain as your main application is a security risk (this blog post from Google security describes the problem well). And in addition to that, using local disk to store and serve your user media makes it harder to scale your application across multiple machines.

For all these reasons, it’s much better to store files on a separate dedicated storage service and serve them to users from there. The django-storages library provides many options e.g. Amazon S3, Azure Storage, and Rackspace CloudFiles.

Easily install Google Fonts

Just as I was doing a website mockup exercise in the awesome Sketch app, I noticed that I’m missing a font locally – Open Sans, one of the many open source fonts available on Google Fonts. I went searching for some Sketch plugin to install these fonts easily (which would make sense, since they are often used on the web as they’re free and some of them are really good). I haven’t found a plug-in, but I did find a nice small Mac app that sits in your tray and allows you to easily install Google Fonts:

SkyFonts

It’s easy to set up by installing it from the above link or using Homebrew Cask:

brew cask install skyfonts

After this, you simply browse Google Fonts on fonts.com and “add” them (you’ll need an account there).

Screenshot 2016-03-04 14.37.29 Continue reading Easily install Google Fonts

Disk on a platter

This article on building a Raspberry Pi NAS solution has been sitting in my drafts for three years now. Recently, my Raspberry Pi had stopped working (the SD card had died), so I rebuilt it yesterday. I cursed myself for not having finishing the text back then, as I now had to retrace some steps manually. So, here goes the finished procedure for future reference.

I got a Raspberry Pi as a birthday present from my thoughtful colleagues!

Raspberry Pi

Now, as my first project I decided to connect it to my 2TB external hard drive and serve it on my local network using the Samba protocol (I tried NFS and SSH too, but Samba proved to be the most performant protocol and is also cross-platform). No more moving the disk around and hooking up USB cables 🙂 Continue reading Disk on a platter

A no fuss Docker install on Rapberry Pi 2

During CloudFleet development, we had some problems in finding a consistent way to install Docker in Debian Jessie on ARM (Raspberry Pi 2). Debian moved us around between mirrors a bit and then eventually settled on Docker 1.7.1 which doesn’t work on ARM (Socket operation on non-socket). Luckily, we found a nice Docker .deb package that works on ARM thanks to the Hypriot community (check the link for the latest Docker version). To use it, simply do:

wget http://downloads.hypriot.com/docker-hypriot_1.8.2-1_armhf.deb
dpkg -i docker-hypriot_1.8.2-1_armhf.deb

Or if you use Ansible, use this snippet: Continue reading A no fuss Docker install on Rapberry Pi 2

Installing CyanogenMod on HTC Sensation

After using the stock Android ICS that came with my Sensation for a couple of years and getting fed up with it crashing and being slow all the time, I decided to try out the CyanogenMod (CM) everyone was talking about. When I started with this endeavour, I was a bit overwhelmed by the amount of incoherent/incomplete resources all around. In this post, I’ll try to summarise the steps necessary to install it in a more human way to help others achieve the same goal.

HTC Sensation and the material design of CM 12
HTC Sensation and the material design of CM 12

Continue reading Installing CyanogenMod on HTC Sensation