Progress Update on Semantic Templates

As it turns out managing templates in an external app for dozens of different apps across 11 different projects is quite a tedious process. We need something simpler. After all, necessity is the mother of invention.

Patrick Altman
The Pinax Project
5 min readOct 18, 2017

--

I wrote back in September that we were moving towards semantic markup for our shipped templates.

Photo by Nigel Tadyanehondo

In order to get there, I had been firing up a starter project instance, pip installing pinax-theme-bootstrap as a local editable and then working back and forth between two editors.

Then as I updated styles in the project instance, I was having to remember what to port back to the starter project. Sometimes I’d forget. Then days go by and I come back and need to work on some templates used in a different starter project so I’d start over.

Sometimes I’d lose the styles I built up.

Sometimes I’d discover we had templates not covered in a particular project.

Other times, I’d need to build up some fixture data, just to populate the templates.

At this rate, I was never going to finish.

Pinax Theme Tester

Wait. I’m an engineer. Repetitive tasks are the devil. Let’s fix that.

This time I started a starter project but when an end in mind. This was going to be able to host all templates we ship, sometimes in multiple different dimensions based on fixture data (empty state, normal state, lots of data state, etc).

This time to add a new set of templates for an app, I shouldn’t have to repeat myself. Maintenance of what I did should be low so that when we change the templates or app, it shouldn’t take much to update things. Porting back styles to the starter projects would be easy but we can do later and we won’t lose anything because we’ll just have a single project and it will be in source control so others can contribute or at least follow along.

Context Switcher

The way this works is you have a drop-down menu on the left that allows you to switch context by picking a configured context (most of these are apps but we needed to support templates that ship outside of a particular app context like pagination/pagination.html).

You just select the template set you want and then you’ll get a context menu on the right to pick the template or view:

After setting the context, the context menu on the right shows all the configured views:

Now when you select a view in the right menu, you are taking to a page that renders the template with mocked context from the theme:

Here is the login form from DUA. It’s instantiating the actual form from DUA and passing it to context.

Configurations

This was all built on the idea of configurations. All you have to do is add a module to the configs/ sub-package. Currently, we have:

There is some cool code in here. Let’s dive in and see how it all works.

First off, let’s take a look at a config:

pinax_theme_tester/configs/announcements.py

Basically what we are doing here is configuring dynamic views and urls with fixture data. A ViewConfigis a simple object:

It just provides some structure and a few common methods.

Some, well most, now, of our apps have namespaces so you can see how we override the resolved_path method in announcements.py to add in the namespace. We generate both urlpatterns as well as a url that will be included in our site urls. You can see that this URL basically includes its own module, picking up the urlpatterns we define in the module.

In the __init__.py we install a config by adding to the CONFIG_MAP:

This is used in the urls.py and context_processors.py:

Pretty lean, right? We just spin through the CONFIG_MAP and add any url we find in the configs, which remember, is an include back to that config’s urlpatterns.

Then the context processor is just then putting the CONFIG_MAP into context as a list of available_configs so that we can populate the two menus dynamically. This eliminates any configuration or hard coding outside creating a config module and hooking it up in the config/__init__.py.

The configuration selector is just a form with a select input that has a bit of js to auto-submit the form on change which goes to a view and sets a session variable of what context you’ve selected.

Then the context menu of views spins through those available_configs and creates menu items:

How I Use It

Now, I am just going through and adding configs for each app. It can take 15 minutes or up to an hour depending on the volume of views and states I need and a number of fixtures required. But once it’s setup, it should be long lasting until views changes in the app which at this point happens rarely.

Once I’ve finished adding the configs, I’ll go back through and focus on creating a SASS module for each app under static/src/scss/apps/*. I’ve created some issues to start publicly tracking what’s left.

Also, it is hosted online at http://templates.pinaxproject.com and gets automatically updated on every push to master.

PRs welcome!

Originally published at blog.pinaxproject.com on October 18, 2017.

--

--