![]() * feat: add benchmarking dashboard, CI hook on PR, and store lifetime results * refactor: change python env to 3.13 in benchmarks * refactor: add verbosity, use 3.11 for benchmarking * fix: OSError: [Errno 7] Argument list too long * refactor: add debug statements * refactor: remove extraneous -e * refactor: fix tests and linter errors * fix: track main package in coverage * refactor: fix test coverage testing * refactor: fix repo owner name in benchmark on pushing comment * refactor: add asv monkeypatch to docs workflow * refactor: temporarily allow building docs in forks * refactor: use py 3.13 for benchmarking * refactor: run only a single benchmark for PRs to speed them up * refactor: install asv in the docs build workflow * refactor: use hatch docs env to generate benhcmarks in docs CI * refactor: more trying * refactor: move tests * Add benchmark results for 0.137 * Trigger Build * Add benchmark results for 0.138 * refactor: set constant machine name when benchmarking * Add benchmark results for 0.139 * refactor: fix issue with paths too long * Add benchmark results for 0.140 * docs: update comment * refactor: remove test benchmarking data * refactor: fix comment * refactor: allow the benchmark workflow to write to PRs * refactor: use personal access token to set up the PR benchmark bot * refactor: split the benchmark PR flow into two to make it work with PRs from forks * refactor: update deprecated actions/upload-artifact@v3 to v4 * refactor: fix missing directory in benchmarking workflow * refactor: fix triggering of second workflow * refactor: fix workflow finally? * docs: add comments to cut-offs and direct people to benchmarks PR --------- Co-authored-by: github-actions <github-actions@github.com> |
||
---|---|---|
.github | ||
benchmarks | ||
docs | ||
logo | ||
sampleproject | ||
scripts | ||
src | ||
tests | ||
.gitignore | ||
.pre-commit-config.yaml | ||
asv.conf.json | ||
CHANGELOG.md | ||
CODE_OF_CONDUCT.md | ||
LICENSE | ||
MANIFEST.in | ||
mkdocs.yml | ||
pyproject.toml | ||
README.md | ||
requirements-ci.in | ||
requirements-ci.txt | ||
requirements-dev.in | ||
requirements-dev.txt | ||
requirements-docs.txt | ||
tox.ini |
Read the full documentation |
⚠️ Attention ⚠️ - We migrated from
EmilStenstrom/django-components
todjango-components/django-components
.Repo name and documentation URL changed. Package name remains the same.
Report any broken links links in #922.
django-components
combines Django's templating system with the modularity seen
in modern frontend frameworks like Vue or React.
With django-components
you can support Django projects small and large without leaving the Django ecosystem.
Quickstart
A component in django-components can be as simple as a Django template and Python code to declare the component:
{# components/calendar/calendar.html #}
<div class="calendar">
Today's date is <span>{{ date }}</span>
</div>
# components/calendar/calendar.html
from django_components import Component
class Calendar(Component):
template_file = "calendar.html"
Or a combination of Django template, Python, CSS, and Javascript:
{# components/calendar/calendar.html #}
<div class="calendar">
Today's date is <span>{{ date }}</span>
</div>
/* components/calendar/calendar.css */
.calendar {
width: 200px;
background: pink;
}
/* components/calendar/calendar.js */
document.querySelector(".calendar").onclick = () => {
alert("Clicked calendar!");
};
# components/calendar/calendar.py
from django_components import Component
class Calendar(Component):
template_file = "calendar.html"
js_file = "calendar.js"
css_file = "calendar.css"
def get_context_data(self, date):
return {"date": date}
Use the component like this:
{% component "calendar" date="2024-11-06" %}{% endcomponent %}
And this is what gets rendered:
<div class="calendar-component">
Today's date is <span>2024-11-06</span>
</div>
Features
Modern and modular UI
- Create self-contained, reusable UI elements.
- Each component can include its own HTML, CSS, and JS, or additional third-party JS and CSS.
- HTML, CSS, and JS can be defined on the component class, or loaded from files.
from django_components import Component
@register("calendar")
class Calendar(Component):
template = """
<div class="calendar">
Today's date is
<span>{{ date }}</span>
</div>
"""
css = """
.calendar {
width: 200px;
background: pink;
}
"""
js = """
document.querySelector(".calendar")
.addEventListener("click", () => {
alert("Clicked calendar!");
});
"""
# Additional JS and CSS
class Media:
js = ["https://cdn.jsdelivr.net/npm/htmx.org@2.1.1/dist/htmx.min.js"]
css = ["bootstrap/dist/css/bootstrap.min.css"]
# Variables available in the template
def get_context_data(self, date):
return {
"date": date
}
Composition with slots
- Render components inside templates with
{% component %}
tag. - Compose them with
{% slot %}
and{% fill %}
tags. - Vue-like slot system, including scoped slots.
{% component "Layout"
bookmarks=bookmarks
breadcrumbs=breadcrumbs
%}
{% fill "header" %}
<div class="flex justify-between gap-x-12">
<div class="prose">
<h3>{{ project.name }}</h3>
</div>
<div class="font-semibold text-gray-500">
{{ project.start_date }} - {{ project.end_date }}
</div>
</div>
{% endfill %}
{# Access data passed to `{% slot %}` with `data` #}
{% fill "tabs" data="tabs_data" %}
{% component "TabItem" header="Project Info" %}
{% component "ProjectInfo"
project=project
project_tags=project_tags
attrs:class="py-5"
attrs:width=tabs_data.width
/ %}
{% endcomponent %}
{% endfill %}
{% endcomponent %}
Extended template tags
django-components
extends Django's template tags syntax with:
- Literal lists and dictionaries in template tags
- Self-closing tags
{% mytag / %}
- Multi-line template tags
- Spread operator
...
to dynamically pass args or kwargs into the template tag - Nested template tags like
"{{ first_name }} {{ last_name }}"
- Flat definition of dictionary keys
attr:key=val
{% component "table"
...default_attrs
title="Friend list for {{ user.name }}"
headers=["Name", "Age", "Email"]
data=[
{
"name": "John"|upper,
"age": 30|add:1,
"email": "john@example.com",
"hobbies": ["reading"],
},
{
"name": "Jane"|upper,
"age": 25|add:1,
"email": "jane@example.com",
"hobbies": ["reading", "coding"],
},
],
attrs:class="py-4 ma-2 border-2 border-gray-300 rounded-md"
/ %}
HTML fragment support
django-components
makes intergration with HTMX, AlpineJS or jQuery easy by allowing components to be rendered as HTML fragments:
-
Components's JS and CSS is loaded automatically when the fragment is inserted into the DOM.
-
Expose components as views with
get
,post
,put
,patch
,delete
methods
# components/calendar/calendar.py
@register("calendar")
class Calendar(Component):
template_file = "calendar.html"
def get(self, request, *args, **kwargs):
page = request.GET.get("page", 1)
return self.render_to_response(
kwargs={
"page": page,
}
)
def get_context_data(self, page):
return {
"page": page,
}
# urls.py
path("calendar/", Calendar.as_view()),
Type hints
Opt-in to type hints by defining types for component's args, kwargs, slots, and more:
from typing import NotRequired, Tuple, TypedDict, SlotContent, SlotFunc
ButtonArgs = Tuple[int, str]
class ButtonKwargs(TypedDict):
variable: str
another: int
maybe_var: NotRequired[int] # May be omitted
class ButtonData(TypedDict):
variable: str
class ButtonSlots(TypedDict):
my_slot: NotRequired[SlotFunc]
another_slot: SlotContent
ButtonType = Component[ButtonArgs, ButtonKwargs, ButtonSlots, ButtonData, JsData, CssData]
class Button(ButtonType):
def get_context_data(self, *args, **kwargs):
self.input.args[0] # int
self.input.kwargs["variable"] # str
self.input.slots["my_slot"] # SlotFunc[MySlotData]
return {} # Error: Key "variable" is missing
When you then call Button.render()
or Button.render_to_response()
, you will get type hints:
Button.render(
# Error: First arg must be `int`, got `float`
args=(1.25, "abc"),
# Error: Key "another" is missing
kwargs={
"variable": "text",
},
)
Debugging features
- Visual component inspection: Highlight components and slots directly in your browser.
- Detailed tracing logs to supply AI-agents with context: The logs include component and slot names and IDs, and their position in the tree.

Sharing components
-
Install and use third-party components from PyPI
-
Or publish your own "component registry"
-
Highly customizable - Choose how the components are called in the template, and more:
{% component "calendar" date="2024-11-06" %} {% endcomponent %} {% calendar date="2024-11-06" %} {% endcalendar %}
Other features
- Vue-like provide / inject system
- Format HTML attributes with
{% html_attrs %}
Documentation
Read the full documentation here.
... or jump right into the code, check out the example project.
Release notes
Read the Release Notes to see the latest features and fixes.
Community examples
One of our goals with django-components
is to make it easy to share components between projects. If you have a set of components that you think would be useful to others, please open a pull request to add them to the list below.
-
django-htmx-components: A set of components for use with htmx. Try out the live demo.
-
djc-heroicons: A component that renders icons from Heroicons.com.
Contributing and development
Get involved or sponsor this project - See here
Running django-components locally for development - See here