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 Django template syntax with a style based on the template style guide in Django’s documentation. It does not format HTML or other templated languages.

Djade is fast because it is built in Rust: benchmarked taking 20ms to format 377 templates.

Read more in the introductory post, or below.


Improve your Django and Git skills with my books.


Installation

Use pip:

python -m pip install djade

Python 3.9 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/engine.html
1 file reformatted

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/engine.html
1 file reformatted

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.

--check

Avoid writing any formatted files back. Instead, exit with a non-zero status code if any files would have been modified, and zero otherwise.

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 %}

Django 1.3+: legacy variable assignment syntax

The minimum target Django version is 2.1, so this fixer is always active.

Django 1.3 added support for = to assign variables in {% with %} and {% blocktranslate %} tags. Prior to this, they only supported the legacy syntax using the as keyword, which Django still supports.

Djade rewrites the older as syntax to the newer = one:

-{% with engines.count as total %}
+{% with total=engines.count %}
     ...
 {% endwith %}

-{% blocktranslate with engine.colour as colour %}
+{% blocktranslate with colour=engine.colour %}
     ...
 {% endblocktranslate %}

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.3.2.tar.gz (35.4 kB view details)

Uploaded Source

Built Distributions

djade-1.3.2-py3-none-win_arm64.whl (831.4 kB view details)

Uploaded Python 3 Windows ARM64

djade-1.3.2-py3-none-win_amd64.whl (908.4 kB view details)

Uploaded Python 3 Windows x86-64

djade-1.3.2-py3-none-win32.whl (823.1 kB view details)

Uploaded Python 3 Windows x86

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

Uploaded Python 3 musllinux: musl 1.1+ x86-64

djade-1.3.2-py3-none-musllinux_1_1_aarch64.whl (1.2 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARM64

djade-1.3.2-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.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl (1.2 MB view details)

Uploaded Python 3 manylinux: glibc 2.17+ i686

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

Uploaded Python 3 manylinux: glibc 2.17+ ARMv7l

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

Uploaded Python 3 manylinux: glibc 2.17+ ARM64

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

Uploaded Python 3 macOS 11.0+ ARM64

djade-1.3.2-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.3.2.tar.gz.

File metadata

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

File hashes

Hashes for djade-1.3.2.tar.gz
Algorithm Hash digest
SHA256 46eaec810cb0ff37ea56885da06f68dedac4529ea80c2b71f0a76801e3ea67e0
MD5 93b8eac94cd347cc3320b37a87e8c4ed
BLAKE2b-256 4fca9d2d7cb8911534e552b01981c30f824ce5f22cc41c3805a95027e476e9cf

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for djade-1.3.2-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 b4afd65e306a79f62cb1891380002ee15056ae6015361bd6699f0c00b2e79b4d
MD5 62d3a431ef6b3da4cc5423e73e5cad61
BLAKE2b-256 a6ad3a83c645c5a2245984346ced7ee9496af109737f33a3006c8bb8c817b442

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for djade-1.3.2-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 6ccab4994e3f655a7e32dcd9e4f2c9c71bb9262bd9a0a29da1ce7ce3fc255c3c
MD5 1f4733cd38f63749d7bb250c39eb229a
BLAKE2b-256 cc6d1aefebf133ba33916cd771ef09d00e6f10226c5e38c48f4334f066c83ade

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for djade-1.3.2-py3-none-win32.whl
Algorithm Hash digest
SHA256 bcc32f3ebb3648b5cd3b9b01ec087748948e30df413eeee2d9abdc99d640c1af
MD5 c0a0640e3c9088e6b15cfc07c5f16700
BLAKE2b-256 d5b803a61712f597440b00973fbc58d3e8f0268bf8f76212372171b04d990401

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 68e214447967fc1dd2adebc42a833fa592f1816cdcfafcfb9054db861917f490
MD5 592189161d00d13c5ba636c33bf3d91d
BLAKE2b-256 845cb143c8186c7434be3fbec20ad90a6c59f5126a46fcd933f3349ca887fa38

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 1a26dd356ceefebea00512bb1e0a8abfc16d7cdf3d08c42569047715e3517c30
MD5 e64d80c7052e618bfe41e99a846e3ea3
BLAKE2b-256 56da6cf27e02b35b0a85b9812ace03cbb2718991eee2840f2b5e491e9be4af7b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 28cc0984fe80de67b7395ed1be9eb31b438fcbe9dabcf1c2c899ad3839365257
MD5 e71ac51d47265a5bcb766269480ccda2
BLAKE2b-256 de61a6bbc23f1ade5a27d4c008dbe092c1ab811009f0f98c51498c6dbefb85a8

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 1a0303e04de45a40397216fd8a9ead58f827c6958c162523a267507f14725357
MD5 e60da57b82c0c18fa75f0d0dc0c40f64
BLAKE2b-256 001847ebe4d079203a7e2addf4a6121f19ea86a446d048b8565eea1c80060034

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 e8ecab5133f85f46a5d1f8b1ff4a1149c70cc8058186c5bbbf8c96003fddb140
MD5 cee1e9e9c89cc892fe0098c9f524ff0e
BLAKE2b-256 d3b97942bfc19b89af85131e909618fed9c521aeab3f78f09dba405058f382a4

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 540ad7115c56d7720d773dbd0f6da4ddb437a6e163936e649f7c94c2fe89bb4d
MD5 e48cc92e4b012aef047fe8612bc237ad
BLAKE2b-256 d767abdb24d6d784b6267050a1a746533bcc9e2d9bc1544ca938056092d823cd

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fe6bbeaf763b4cd0099d0659aee119f4cba1eed118a041db5dd589f742c4e2a1
MD5 c21feca49d912f5d834ae6df71dae910
BLAKE2b-256 c035e94b2d86e13884317cfbddbd0fa6b977c2d886c9e880a66a93c177a4b2f1

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.2-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 55558103c43332bd16aa2c71ce97eb5d938d53fce234cb37679b0749fdbeb005
MD5 747bb2bb865de827432502f3f98a9a83
BLAKE2b-256 7bcd2aff9df9a709a753d22bf3ebfbff813d35052ac30e2de6328820b0cfa9aa

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