Themes

A DJ Press theme is a collection of Django template files and static assets that control the look and feel of your blog. This guide explains how to use existing themes, customise them, or create your own theme from scratch.

Theme Structure

Template Files

Template files must be placed in: ./templates/djpress/{{ your_theme_name }}/

At minimum, a theme needs an index.html template. If this is the only template you provide, it will be used for all views. For more specialised layouts, you can create these additional templates:

Template Name

Used For

Example URL

home.html

Home page

https://yourblog.com/

single.html

Individual posts

https://yourblog.com/2024/05/20/my-post/

page.html

Static pages

https://yourblog.com/about/

archives.html

Date-based archives

https://yourblog.com/2024/

category.html

Category pages

https://yourblog.com/category/news/

tag.html

Tag pages

https://yourblog.com/tag/python/

author.html

Author pages

https://yourblog.com/author/sam/

When a specific template isn’t available, DJ Press falls back to index.html.

Static Files

Static files (CSS, JavaScript, images) should be placed in: ./static/djpress/{{ your_theme_name }}/

Recommended organisation:

  • ./static/djpress/{{ your_theme_name }}/css/

  • ./static/djpress/{{ your_theme_name }}/js/

  • ./static/djpress/{{ your_theme_name }}/img/

Access static files in your templates using the Django static tag:

{% load static %}
<link rel="stylesheet" href="{% static 'djpress/mytheme/css/style.css' %}">
<script src="{% static 'djpress/mytheme/js/main.js' %}"></script>
<img src="{% static 'djpress/mytheme/img/logo.png' %}" alt="Logo">

Activating a Theme

To use a theme, set the THEME setting in your Django project’s settings:

DJPRESS_SETTINGS = {
    "THEME": "mytheme",
}

The theme name must match the directory name under templates/djpress/ and static/djpress/.

Creating a Custom Theme

Creating a custom theme involves these steps:

  1. Create the necessary directories:

    mkdir -p templates/djpress/mytheme
    mkdir -p static/djpress/mytheme/css
    mkdir -p static/djpress/mytheme/js
    mkdir -p static/djpress/mytheme/img
    
  2. Create an index.html template (minimum requirement):

    {% load static %}
    {% load djpress_tags %}
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>{% page_title post_text="| " %}{% site_title %}</title>
        <link rel="stylesheet" href="{% static 'djpress/mytheme/css/style.css' %}">
        {% rss_link %}
    </head>
    <body>
        <header>
            <h1>{% site_title_link %}</h1>
            <nav>{% site_pages %}</nav>
        </header>
    
        <main>
            {% if post %}
                {% post_wrap %}
                    <h1>{% get_post_title %}</h1>
                    <div class="meta">
                        By {% post_author %} | {% post_date %}
                    </div>
                    <div class="content">
                        {% post_content %}
                    </div>
                    <div class="taxonomy">
                        Categories: {% post_categories %}
                        Tags: {% post_tags %}
                    </div>
                {% end_post_wrap %}
            {% else %}
                <h1>Latest Posts</h1>
                {% for post in posts %}
                    {% post_wrap %}
                        <h2>{% post_title %}</h2>
                        <div class="meta">
                            By {% post_author %} | {% post_date %}
                        </div>
                        <div class="content">
                            {% post_content %}
                        </div>
                    {% end_post_wrap %}
                {% empty %}
                    <p>No posts found.</p>
                {% endfor %}
    
                {% pagination_links %}
            {% endif %}
        </main>
    
        <aside>
            <h3>Categories</h3>
            {% blog_categories %}
    
            <h3>Tags</h3>
            {% blog_tags %}
    
            <h3>Archives</h3>
            <!-- Custom archive links could go here -->
        </aside>
    
        <footer>
            <p>&copy; {% now "Y" %} | Powered by DJ Press</p>
        </footer>
    </body>
    </html>
    
  3. Create a basic CSS file (static/djpress/mytheme/css/style.css):

    /* Basic styling for the theme */
    body {
        font-family: system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
        line-height: 1.6;
        margin: 0;
        padding: 0;
        display: grid;
        grid-template-columns: 1fr 300px;
        grid-template-areas:
            "header header"
            "main sidebar"
            "footer footer";
        gap: 20px;
        max-width: 1200px;
        margin: 0 auto;
        padding: 20px;
    }
    
    header {
        grid-area: header;
        border-bottom: 1px solid #eee;
        padding-bottom: 20px;
        margin-bottom: 20px;
    }
    
    main {
        grid-area: main;
    }
    
    aside {
        grid-area: sidebar;
        background: #f7f7f7;
        padding: 20px;
        border-radius: 5px;
    }
    
    footer {
        grid-area: footer;
        border-top: 1px solid #eee;
        padding-top: 20px;
        margin-top: 20px;
        text-align: center;
    }
    
    article {
        margin-bottom: 30px;
        padding-bottom: 20px;
        border-bottom: 1px solid #eee;
    }
    
    h1, h2, h3 {
        color: #333;
    }
    
    a {
        color: #0066cc;
        text-decoration: none;
    }
    
    a:hover {
        text-decoration: underline;
    }
    
    .meta {
        color: #666;
        font-size: 0.9em;
        margin-bottom: 15px;
    }
    
    .taxonomy {
        font-size: 0.9em;
        margin-top: 15px;
    }
    
  4. Activate your theme in settings:

    DJPRESS_SETTINGS = {
        "THEME": "mytheme",
    }
    

Template Context

DJ Press provides these context variables to your templates:

Context Variable

Type

Available In

Description

post

Post object

Single post/page views

The current post or page

posts

Paginator Page

Index views

Collection of posts for the current page

category

Category object

Category views

The current category

author

User object

Author views

The current author

tags

List of Tag objects

Tag views

The current tag(s)

Conditional Template Logic

You can use conditional logic to create different layouts based on the view type:

{% if post %}
    {# Single post/page view #}
    <h1>{{ post.title }}</h1>
{% elif category %}
    {# Category view #}
    <h1>Category: {{ category.title }}</h1>
{% elif author %}
    {# Author view #}
    <h1>Posts by {{ author.get_full_name }}</h1>
{% else %}
    {# Home or archive view #}
    <h1>Blog Posts</h1>
{% endif %}

Built-in Themes

DJ Press includes two reference themes:

  1. default - A minimalist theme with a single index.html template

  2. simple - A basic theme that demonstrates using different template types

You can use these as starting points for your own themes.

Advanced Theme Techniques

Template Inheritance

For more maintainable themes, use Django’s template inheritance:

{# base.html #}
<!DOCTYPE html>
<html>
<head>
    <title>{% block title %}{% site_title %}{% endblock %}</title>
    {% block head %}{% endblock %}
</head>
<body>
    <header>{% block header %}{% endblock %}</header>
    <main>{% block content %}{% endblock %}</main>
    <footer>{% block footer %}{% endblock %}</footer>
</body>
</html>
{# single.html #}
{% extends "djpress/mytheme/base.html" %}

{% block title %}{{ post.title }} | {% site_title %}{% endblock %}

{% block content %}
    <article>{{ post.content_markdown }}</article>
{% endblock %}

Custom Filters

You can create custom template filters for your theme by creating a templatetags directory in your app. But if there are missing tags, then it would help us to raise an issue on GitHub so we can consider adding them in DJ Press core.