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 iss 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.0.tar.gz (34.9 kB view details)

Uploaded Source

Built Distributions

djade-1.3.0-py3-none-win_arm64.whl (831.7 kB view details)

Uploaded Python 3 Windows ARM64

djade-1.3.0-py3-none-win_amd64.whl (908.9 kB view details)

Uploaded Python 3 Windows x86-64

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

Uploaded Python 3 Windows x86

djade-1.3.0-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.0-py3-none-musllinux_1_1_aarch64.whl (1.2 MB view details)

Uploaded Python 3 musllinux: musl 1.1+ ARM64

djade-1.3.0-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.0-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.0-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.0-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.0-py3-none-macosx_11_0_arm64.whl (1.0 MB view details)

Uploaded Python 3 macOS 11.0+ ARM64

djade-1.3.0-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.0.tar.gz.

File metadata

  • Download URL: djade-1.3.0.tar.gz
  • Upload date:
  • Size: 34.9 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.0.tar.gz
Algorithm Hash digest
SHA256 a72bc81d6c47ec2cd35400b8aed5473dfbd4ae72df9c2a029929dc56687afc43
MD5 df0e296ca2e73d904fb95509b815c0cf
BLAKE2b-256 b633be00b78528bfcc2b32166ba1fdadfa75f62ce3de7615342c4826697de92f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: djade-1.3.0-py3-none-win_arm64.whl
  • Upload date:
  • Size: 831.7 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.0-py3-none-win_arm64.whl
Algorithm Hash digest
SHA256 493aec6d459002905bd17642dff499ddd806cd018bd9113389b7938785d3d16c
MD5 26ffb25f95d22cf5787eca1cf3cacb65
BLAKE2b-256 ed54699be982b5a99ab7cffb0486fcdd9a23b2a4c70d809bbfa40e6812a29982

See more details on using hashes here.

File details

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

File metadata

  • Download URL: djade-1.3.0-py3-none-win_amd64.whl
  • Upload date:
  • Size: 908.9 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.0-py3-none-win_amd64.whl
Algorithm Hash digest
SHA256 f3bd8debf6067fc3682e35c606355d0b8e40489927076be09381a1ea769f5225
MD5 6fb432405cbee03c716fa9199966d4cc
BLAKE2b-256 7692d3ecf4190edd9c5f0c1c16df871f27129031c4ec2d5ad6538f1c28364432

See more details on using hashes here.

File details

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

File metadata

  • Download URL: djade-1.3.0-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.0-py3-none-win32.whl
Algorithm Hash digest
SHA256 fd0efa0253935b2c7e93994de33701e9722849f83bb5e51181a8c3290b41b5a1
MD5 0d0aa92cf43437c29b1d6570fa154cae
BLAKE2b-256 5fa721cd0ae9fa862931b616e2b71e7a99eebb55d0ca8bbd3507a39df20cc855

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 f692d5015395494b9ee6ca9c18ec210178f9fae1f194786391b7fa0f908055a0
MD5 dc2f8152d6ee9249cfb8f216489e1980
BLAKE2b-256 2a0b163d82f8b5071047f19b46199a8a3a5000f90b0997a45a0d2d3137de80aa

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 eaa5fc3436a42d542b3c4ffff8807b8d87ea8dc25488d9fb4c66d22c7daae010
MD5 5ff89aa2e00cab9e15d9490f28d87315
BLAKE2b-256 d627f3149584e3ba0843fcc6761a4dbda7013e4787f542ed9c3d391065759990

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 d7b02b92c9caab62173cb57561cca8bf4eeef4ae2ff2d481f017c6fedf1bef67
MD5 21230dd7267d6d78892f4a75df10f92f
BLAKE2b-256 b0c1a3b33192213bedd312b8b85963336b0aed9302b102e486a551b8da6ded8b

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl
Algorithm Hash digest
SHA256 78694c152352469cae99d3a97d8e4e4839557b307088b33d4abc97bdc48112b8
MD5 2ccee877ad8ae493eaedd2e638ec2cda
BLAKE2b-256 bc61f424d5b927aa8998e56c2b81e4f4f13ee820f93f2ff6b6a956cb564c82a3

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 362630e49c2a809a3599ff66c5125cfd78c5b045c77756a4679737bd0b9cc235
MD5 377e97851f1f8f15db8b08d1a9104ef9
BLAKE2b-256 c770886ed46d75ee68963ed64b23e24a6a9c229f23c414d6da7baab21fa6888e

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 a174245987199904f8502068e24be5061a51660c3330d9853318ad98b8659fde
MD5 4926e2965856408f2af892a474536bbc
BLAKE2b-256 7028f7b8c0b546d4234fd15cffc108274e0075ce5ab735eb34f22302fe22fd18

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 cb390b65bfa52ff6d7c68b35edfea5b807e582dea1c74c8b19270cc8dfba11c3
MD5 dca1b9a8c8c8db9858a19b81b53a1b7c
BLAKE2b-256 915e6fc5de51d130fb4afa803a701d7e4a6b95ed0859393bd2b4a0a8198d9320

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for djade-1.3.0-py3-none-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 4604649877feb020e66a6c85d8dacf29a257f7c62efe7599795944a1b06e3e43
MD5 c3a1ab77d9b04ce81e207f6969bb31ac
BLAKE2b-256 e6e1df59f895b20b8d600624aa3e9a9f4574150cfd277f406864016fb9005e21

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