Skip to main content

A Django template formatter.

Project description

https://img.shields.io/github/actions/workflow/status/adamchainz/djade/main.yml.svg?branch=main&style=for-the-badge https://img.shields.io/pypi/v/djade.svg?style=for-the-badge pre-commit
You can have any colour you like, as long as it’s jade.

A Django template formatter.

You can have any colour you like, as long as it’s [d]jade.

Djade formats templates with a style based on the template style guide in Django’s documentation. It’s built in Rust, which makes it fast: benchmarked taking 20ms to format 377 templates.

Read more in the introductory post.


Improve your Django and Git skills with my books.


Installation

Use pip:

python -m pip install djade

Python 3.8 to 3.13 supported.

pre-commit hook

You can also install Djade as a pre-commit hook.

First, add the following to the repos section of your .pre-commit-config.yaml file (docs):

-   repo: https://github.com/adamchainz/djade-pre-commit
    rev: ""  # Replace with the latest tag on GitHub
    hooks:
    -   id: djade
        args: [--target-version, "5.1"]  # Replace with Django version

The separate repository enables installation without compiling the Rust code.

The default configuration uses pre-commit’s files option to pick up all text files in directories called templates (source). You may wish to override this if you have templates in different directories by adding files to the hook configuration in your .pre-commit-config.yaml file.

Second, format your entire project:

pre-commit run djade --all-files

Check these changes for any potential Djade bugs and commit them. Try git diff --ignore-all-space to check non-whitespace changes.

Third, consider adding the previous commit SHA to a .git-blame-ignore-revs file. This will prevent the initial formatting commit from showing up in git blame.

Keep the hook installed to continue formatting your templates. pre-commit’s autoupdate command will upgrade Djade so you can take advantage of future features.

Usage

djade is a command line tool that rewrites files in place. Pass a list of template files to format them:

$ djade --target-version 5.1 templates/**/*.html
Rewriting templates/locomotives/steam_engine.html
Rewriting templates/locomotives/diesel.html

Djade can also upgrade some old template syntax. Add the --target-version option with your Django version as <major>.<minor> to enable applicable fixers:

$ djade --target-version 5.1 templates/**/*.html
Rewriting templates/locomotives/steam_engine.html

Djade does not have any ability to recurse through directories. Use the pre-commit integration, globbing, or another technique to apply it to many files. For example, with git ls-files | xargs:

git ls-files -z -- '*.html' | xargs -0 djade

…or PowerShell’s ForEach-Object:

git ls-files -- '*.html' | %{djade $_}

Options

--target-version

Optional: the version of Django to target, in the format <major>.<minor>. If provided, Djade enables its fixers for versions up to and including the target version. See the list of available versions with djade --help.

Formatting

Djade aims to format Django template syntax in a consistent, clean way. It wants to be like Black: opinionated and free of configuration. Djade’s style is based on the rules listed in the Django contribution style guide’s template style section, plus some more.

Djade does not aim to format the host language of templates (HTML, etc.). That is a much broader scope and hard to do without semantic changes. For example, whitespace is significant in some HTML contexts, such as in <pre> tags, so even adjusting indentation can affect the meaning.

Below are the rules that Djade implements.

Rules from the Django style guide:

  • Single spaces at the start and end of variables and tags:

    -{{train}}
    +{{ train }}
    
    -{%  blow whistle  %}
    +{% blow whistle %}
  • Label {% endblock %} tags that aren’t on the same line as their opening {% block %} tag:

     {% block funnel %}
     ...
    -{% endblock %}
    +{% endblock funnel %}
  • Sort libraries in {% load %} tags:

    -{% load coal boiler %}
    +{% load boiler coal %}
  • Inside variables, no spaces around filters:

    -{{ fire | stoke }}
    +{{ fire|stoke }}
  • Inside tags, single spaces between tokens:

    -{% if  locomotive  ==  'steam engine'  %}
    +{% if locomotive == 'steam engine' %}
  • Unindent top-level {% block %} and {% endblock %} tags when {% extends %} is used:

    -  {% extends 'engine.html' %}
    +{% extends 'engine.html' %}
    
    -  {% block boiler %}
    +{% block boiler %}
       ...
    -  {% endblock boiler %}
    +{% endblock boiler %}

Extra rules:

  • No leading empty lines:

    -
     {% extends 'engine.html' %}
     ...
  • No trailing empty lines:

     ...
     {% endblock wheels %}
    -
    -
  • Single spaces at the start and end of comments:

    -{#choo choo#}
    +{# choo choo #}
  • No labels in {% endblock %} tags on the same line as their opening {% block %} tag:

    -{% block funnel %}...{% endblock funnel %}
    +{% block funnel %}...{% endblock %}
  • Merge consecutive {% load %} tags:

    -{% load boiler %}
    -
    -{% load coal %}
    +{% load boiler coal %}
  • Sort loaded items in {% load ... from .. %} tags:

-{% load steam heat from boiler %}
+{% load heat steam from boiler %}
  • Unindent {% extends %} tags:

    -  {% extends 'engine.html' %}
    +{% extends 'engine.html' %}
  • Exactly one blank line between top-level {% block %} and {% endblock %} tags when {% extends %} is used:

 {% extends 'engine.html' %}

-
 {% block funnel %}
   ...
 {% endblock funnel %}
+
 {% block boiler %}
   ...
 {% endblock boiler %}

Fixers

Djade applies the below fixes based on the target Django version from --target-version.

Django 4.2+: length_is -> length

From the release note:

The length_is template filter is deprecated in favor of length and the == operator within an {% if %} tag.

Djade updates usage of the deprecated filter within if tags, without other conditions, appropriately:

-{% if engines|length_is:1 %}
+{% if engines|length == 1 %}

Django 4.1+: empty ID json_script fixer

From the release note:

The HTML <script> element id attribute is no longer required when wrapping the json_script template filter.

Djade removes the argument where json_script is passed an empty string, to avoid emitting id="":

-{% tracks|json_script:"" %}
+{% tracks|json_script %}

Django 3.1+: trans -> translate, blocktrans / endblocktrans -> blocktranslate / endblocktranslate

From the release note:

The renamed translate and blocktranslate template tags are introduced for internationalization in template code. The older trans and blocktrans template tags aliases continue to work, and will be retained for the foreseeable future.

Djade updates the deprecated tags appropriately:

-{% load blocktrans trans from i18n %}
+{% load blocktranslate translate from i18n %}

-{% trans "Engine colours" %}
+{% translate "Engine colours" %}

-{% blocktrans with colour=engine.colour %}
+{% blocktranslate with colour=engine.colour %}
 This engine is {{ colour }}.
-{% endblocktrans %}
+{% endblocktranslate %}

Django 3.1+: ifequal and ifnotequal -> if

From the release note:

The {% ifequal %} and {% ifnotequal %} template tags are deprecated in favor of {% if %}.

Djade updates the deprecated tags appropriately:

-{% ifequal engine.colour 'blue' %}
+{% if engine.colour == 'blue' %}
 Thomas!
-{% endifequal %}
+{% endif %}

-{% ifnotequal engine.colour 'blue' %}
+{% if engine.colour != 'blue' %}
 Not Thomas.
-{% endifnotequal %}
+{% endif %}

Django 2.1+: admin_static and staticfiles -> static

From the release note:

{% load staticfiles %} and {% load admin_static %} are deprecated in favor of {% load static %}, which works the same.

Djade updates {% load %} tags appropriately:

-{% load staticfiles %}
+{% load static %}

-{% load admin_static %}
+{% load static %}

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

djade-1.1.1.tar.gz (32.4 kB view details)

Uploaded Source

Built Distributions

djade-1.1.1-py3-none-win_arm64.whl (825.8 kB view details)

Uploaded Python 3 Windows ARM64

djade-1.1.1-py3-none-win_amd64.whl (902.4 kB view details)

Uploaded Python 3 Windows x86-64

djade-1.1.1-py3-none-win32.whl (817.2 kB view details)

Uploaded Python 3 Windows x86

djade-1.1.1-py3-none-musllinux_1_1_x86_64.whl (1.2 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ x86-64

djade-1.1.1-py3-none-musllinux_1_1_aarch64.whl (1.1 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARM64

djade-1.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ x86-64

djade-1.1.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (1.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ i686

djade-1.1.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (1.1 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

djade-1.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (1.1 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

djade-1.1.1-py3-none-macosx_11_0_arm64.whl (1.0 MB view details)

Uploaded Python 3 macOS 11.0+ ARM64

djade-1.1.1-py3-none-macosx_10_12_x86_64.whl (1.1 MB view details)

Uploaded Python 3 macOS 10.12+ x86-64

File details

Details for the file djade-1.1.1.tar.gz.

File metadata

  • Download URL: djade-1.1.1.tar.gz
  • Upload date:
  • Size: 32.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.1.tar.gz
Algorithm Hash digest
SHA256 afbc1859e7a113f84bdf7d7f1e633aa32ba8a9a067a3d188cd9282c069854c44
MD5 b62a4556c33ddb40492544ae86cf0c83
BLAKE2b-256 c09e8d2008e90776a56c4c3efa603c96c1fa55a98433a270a57942cf780189be

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-win_arm64.whl.

File metadata

  • Download URL: djade-1.1.1-py3-none-win_arm64.whl
  • Upload date:
  • Size: 825.8 kB
  • Tags: Python 3, Windows ARM64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.1-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 7f6d3ea968d6e186a634c9a6cfcae8cb432c26775042e5c8fcce9feb74adccd9
MD5 301f9498568dbfe35416d589edf31965
BLAKE2b-256 595f74e35900d309c60d4aa68b59996ce7cdddbf6efd695b809f595273995f43

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-win_amd64.whl.

File metadata

  • Download URL: djade-1.1.1-py3-none-win_amd64.whl
  • Upload date:
  • Size: 902.4 kB
  • Tags: Python 3, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.1-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 9b251e41e71b5f53beaa60b562cbe94bc8cd87d9225ac50929d1023bad26f19a
MD5 995d06507d764680c9096b5b4e619d16
BLAKE2b-256 3f218ad254199204a4f22191bbeea647753a207fb624966eb790351ae40126ea

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-win32.whl.

File metadata

  • Download URL: djade-1.1.1-py3-none-win32.whl
  • Upload date:
  • Size: 817.2 kB
  • Tags: Python 3, Windows x86
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.1.1 CPython/3.12.6

File hashes

Hashes for djade-1.1.1-py3-none-win32.whl
Algorithm Hash digest
SHA256 ddf79f75f6bb14bd4971b6ef6e80f9f2ffe747dc80d6b9c56d26b37d0a329e70
MD5 3f55fa72f1da24ed1f53a02d4328224e
BLAKE2b-256 ae901ef62c65930efb89bbcb29e6e1658b691ceb4cee3965a7cdf6317a6f71f0

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 2b29b6d0bf1d870700091897bd9d4c12d72be6d7222c644ab8d5fd7d4846b36f
MD5 60776928c1e4bc1f7f35946cfd75ccc4
BLAKE2b-256 80afd925194f80e54a46820e0032cb4f7e6abdae191749d6c53263603a9191cf

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 c95dff339f8ac01b0c72f2c59e9e4323f01376ae325e413c0231ae23782063c8
MD5 03d8ffce461ef6cc6ea3d70b35d96e32
BLAKE2b-256 4897bcf24390305da60c65e9d3ad00441ac26771dd022ec3dea0ff7b8e16f60d

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 91db10a4e3d3f8741a1b37d0652001bc7a66d931a679f1beaf43c5f23d8f2b93
MD5 618f33427aa40935243d681661bd68f1
BLAKE2b-256 10986cf6f602a71d56b6de6add73609e3e508823be3285d405e22f85e92e63b7

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 3d473a37c6f793ff9ca7caaf7504e8ebf112eeb2881f16ce20102f2da4b90aab
MD5 f85f5a845ceebcb97865bce7a3d32adb
BLAKE2b-256 73e3bbc255469f9538a6dfaf375e6a44b3627f22a390140f25359503ac3c53c3

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 ebd9ceba20a385aea9d978e9f544c2424efe032075bd0f508cab52f465f0f65a
MD5 b81632794234bf66ae4a223045f7e0d8
BLAKE2b-256 4dcc79d676f56cf62ed416d3968f3056355a5948516179e61db120e4bda5bb38

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 4d6bac6af64a162ec3d9ccbb79dfdfd26b23991300df84585b155a65cf8a673d
MD5 f1090a9fab125492e294cec5c29b0241
BLAKE2b-256 37910bdfc4dc4477679eaa9e2c3e331d811636d5bcc4429ecab2fef49ccfd19b

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 ab75f5624334e585abd5e4805e615ce2cedfc0c595f2c1d0c19a80b1e4293939
MD5 618aa1d2227754355f4e903d96557204
BLAKE2b-256 1d3754a6046d3a5d0112a0deb9e7c50fd143507d457826e82320c6cf75f359a3

See more details on using hashes here.

File details

Details for the file djade-1.1.1-py3-none-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for djade-1.1.1-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 91f18951314c744deb0bd811a3334920c471fa0665f13933a1daa0123173387e
MD5 37f84addb53a51523923c939ea6bbba0
BLAKE2b-256 9caa3ee09ff41eab9f90d45327095ecc855d71c3d69f11e94a56674e47052cf4

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page