Posts Photos Archives About

Stylesheet Switcher using Django

You may have noticed the new color scheme and new "Theme Switcher" widget in the sidebar. I had done some CSS work during the past month in the office and it made me want to tweak the stylesheets on this site a bit. I figured I might as well make it easy to switch stylesheets, so I wrote a small Theme Switcher django app. (Well, it's more of a stylesheet switcher I guess)

The model is simple:

class Theme(models.Model):
    slug = models.SlugField()
    title = models.CharField(max_length=250)
    css_path = models.CharField(max_length=500)

    def __str__(self):
        return self.title

I only needed one view -- to switch the current theme.

Added the ff to

(r'^theme/([a-zA-Z0-9\-]+)/', 'themer.views.switch'),

The view code simply stores the selected theme as a cookie:

def switch(request, theme_slug):
  """ Sets a cookie to specify the new theme, then redirects to the referer or root url """
  theme = get_object_or_404(Theme, slug=theme_slug)
  referer = "/"
  if "HTTP_REFERER" in request.META:
    referer = request.META["HTTP_REFERER"]
  resp = HttpResponseRedirect(referer)
  resp.set_cookie("theme", theme_slug, 100000)
  return resp

To load the stylesheet, I set up a context processor to pass both the current theme and the list of themes to the context. I wanted to do this using template tags, but I couldn't figure out how to extract a cookie from within a template tag.

from themer.models import Theme
def context_processor(request):
    theme_list = Theme.objects.all()
    if "theme" in request.COOKIES:
        slug = request.COOKIES["theme"]
            theme = Theme.objects.get(slug=slug)
        except Theme.DoesNotExist:
            theme = None
        if theme_list.count() > 0:
            theme = theme_list[0]
            theme = None
    return {"current_theme" : theme, "theme_list" : theme_list}

Then in my base template file, I add the following to the head section:

<link rel="stylesheet" href="{{ current_theme.css_path }}" type="text/css" />

And add the list of themes into the sidebar.

<h2>Theme Switcher</h2>
            {% for theme in theme_list %}
            {% ifequal theme.slug current_theme.slug %}
            {{ theme.title }} <span class="note">(current)</span>
            {% else %}
            <a href="{% url themer.views.switch theme.slug %}" title="Switch to {{ theme.title }} theme">{{ theme.title }}</a>
            {% endifequal %}
            {% endfor %}

And we're done!

Of course, I'm still not particularly strong in web design, so the two current "themes" really just switch around the color scheme. The light blue theme is named Azorius, while the old black and green theme is named Golgari, both named after the respective color guilds in Magic: The Gathering's Ravnica block.

Hopefully this gives me a chance to whip up more interesting themes and polish the old CSS skills some more. Enjoy!

# / / blog / #royondjango #django #python #software-development / 💬 2 / 406 words

Last modified at: Jan. 17, 2021, 4:57 a.m. Source file


Radek said...


Nice do you have working example or download that I can try and look how it works?

roy said...

Hi Radek, unfortunately I'm unable to find the original source code for this; I had previously been running a Django-backed blog but have since migrated it and the posts over to Wordpress