Switching to django-compressor in Playdoh

Around six months ago the Mozilla Playdoh project, a web application template based on Django, switched from using jingo-minify to using django-compressor for all things ‘combinable’ and ‘minifiyable’. Along with this we started using the staticfiles app i.e. django.contrib.staticfiles.

Both of these have been positive moves and while funfactory does most of the heavy lifting to upgrade your project successfully, or setting it up if it’s a recent clone, to use the above, there are still some changes you need to be aware of and make manually. These are the items I will then cover in this post.

NOTE: I here assume that you have already created and setup a basic Playdoh project using the Playdoh documentation here.

Referencing Static Files

The first thing we need to look at is how static files are references when using the new libraries. If you have been using jingo-minify you will be used to creating bundles in settings/base.py and then referencing those bundles in your template, for example:

Now with django-compressor there is nothing to do in your settings and you would include your assets as follows:

Now in late January of this year (2012) the project layout of Playdoh projects also changed in the sense that is no more apps nor media directory and instead, there is a ‘projectname’ folder. The great thing about this combined with the above two is that it is now possible to keep the assets needed for your app right there with your templates, views etc.

So, what does a typical project layout look like?

Well after funfactory has created your app you will have a structure as follows (looking only at the folder related to you project):

projectname
-- base
---- templates
------ .gitignore
------ 404.html
------ 500.html
------ example_base.html
---- __init__.py
---- models.py
-- examples
---- static
------ examples
-------- css
-------- js
---- templates
------ examples
-------- mobile
---------- ...
-------- bleach.html
-------- home.html
---- __init__.py
---- models.py
---- urls.py
---- views.py
-- locale
---- ...
-- settings
---- ...
__init__.py
urls.py

Whoah, that is a lot but, for the purpose of this post we are only interested in the base and examples folder. Going from the top, go ahead and create a folder called static inside the base folder and in this folder you can then store all of your core static assets such as your images, CSS/LESS and JS etc.

Next you can either create a new folder at the root of your project folder that matches your projectname and remove the examples folder or, rename the examples folder to match your project’s name (this is what is assumed here, so most things will already be there but follow along) and remove anything you will not need. Inside this folder move into the static folder and again rename examples to your project’s name and do the same inside the templates folder. You should end up with something like:

-- base
---- static
------ css
------ img
------ js
---- templates
------ .gitignore
------ 404.html
------ 500.html
------ base.html
---- __init__.py
---- models.py
-- projectname
---- static
------ projectname
-------- css
-------- js
---- templates
------ projectname
-------- home.html
---- __init__.py
---- models.py
---- urls.py
---- views.py

Before we can start coding, we need to add something to our urls file to make development smoother i.e. you do not need to run the collectstatic command every time you add something new or make a change to an existing file. Inside the root folder of your project open the urls.py folder and add the following (This might already be present so double check before adding):

Now we are ready to code our project and use our static assets. Inside your base folder open up the base.html (if it is still called example_base.html, rename it) folder. Inside the head section of you page add the following to link your main CSS:

As you can see here we are using the static function inside the href of the link tag to point to the file we want to include, we also wrap this up in a site_css block, that will come in handy in a minute, as well as using compress css. The site_css block gives us a hook that we can later use to override what is in base or, add something additional. The compress css will ensure that what is inside it will be minified and potentially preprocessed if you use, for example LESS (as is the case in these examples).

NOTE: If you are using LESS you need to ensure that you have Node.js and the lessc preprocessor installed and that it is in your PATH. For more on this see the LESS website’s server side section. Also, django-compressor has built in support for LESS by default and will as such recognize the use of text/less as the value for the type attribute on the link tag.

Next, move into your projectname/templates/projectname folder and open up index.html

As you can see from the above we here use the site_css tag from before and then call super() which will ensure the file(s) defined in the template we are extending is included as well as the new file(s) we are adding for this specific template. The one difference you will notice is that inside the index.html file, instead of using css/ourfile.less, we are prefixing it with projectname/css/ourfile.less, this is to inform Playdoh that you want to load the file from the static folder of your projectname folder and not base.

The same then also goes for including images as well as JavaScript but, with JavaScript there is a slight difference:

The main difference being creating a block called site_js and then calling compress js inside your block. Inside your template extending base, the usage is then the same as before with this one change.

This should then get you up and running quickly and easily using django-compressor, the staticfiles app and the new project layout of Playdoh. If there is something I missed or you have any additional comments or questions, please feel free to add them in the comments.

3 responses

  1. Ross Bruniges wrote on :

    I was hoping someone would right something about this after going through rather a bit of pain myself when having to upgrade!

    One thing you missed (and caused me rather a lot of head scracting) is that if you reference images/fonts in your CSS files then the usage of ../ URLs will now break. Not sure if this is the best solution but I got around this by referencing everything instead to be /static/ – so url(‘..img/css/check.png’) would be replaced by url(‘/static/base/img/css/check.png’)

    Also, am wondering how using staticfiles effects the usage of any image upload fields used in the app? This will still use the old {{ MEDIA_URL }} yeah? Should it be changed to use static or just left as is?

  2. Schalk Neethling wrote on :

    Hey there Ross,

    Regarding the use of static for linking from within CSS, I do exactly the same. Regarding the use of static for file uploads, I am not sure but, will pass the question around and update the post once I have a definitive answer. Thanks for the comment.

  3. James Socol wrote on :

    They broke out staticfiles from media to create a distinction between uploaded content and static content, so

    MEDIA_URL/MEDIA_PATH – user uploads
    STATIC_URL/STATIC_PATH – static files from your app