A RetroSearch Logo

Home - News ( United States | United Kingdom | Italy | Germany ) - Football scores

Search Query:

Showing content from https://github.com/django-components/django-components/ below:

django-components/django-components: Create simple reusable template components in Django.

django-components is a modular and extensible UI framework for Django.

It 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.

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.py
from django_components import Component, register

@register("calendar")
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, register

@register("calendar")
class Calendar(Component):
    template_file = "calendar.html"
    js_file = "calendar.js"
    css_file = "calendar.css"

    def get_template_data(self, args, kwargs, slots, context):
        return {"date": kwargs["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>

Read on to learn about all the exciting details and configuration possibilities!

(If you instead prefer to jump right into the code, check out the example project)

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/dist/htmx.min.js"]
        css = ["bootstrap/dist/css/bootstrap.min.css"]

    # Variables available in the template
    def get_template_data(self, args, kwargs, slots, context):
        return {
            "date": kwargs["date"]
        }
{% 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 %}

django-components is designed for flexibility, making working with templates a breeze.

It extends Django's template tags syntax with:

{% 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"
/ %}

You too can define template tags with these features by using @template_tag() or BaseNode.

Read more on Custom template tags.

When you render a component, you can access everything about the component:

class Table(Component):
    js_file = "table.js"
    css_file = "table.css"

    template = """
        <div class="table">
            <span>{{ variable }}</span>
        </div>
    """

    def get_template_data(self, args, kwargs, slots, context):
        # Access component's ID
        assert self.id == "djc1A2b3c"

        # Access component's inputs and slots
        assert self.args == [123, "str"]
        assert self.kwargs == {"variable": "test", "another": 1}
        footer_slot = self.slots["footer"]
        some_var = self.context["some_var"]

        # Access the request object and Django's context processors, if available
        assert self.request.GET == {"query": "something"}
        assert self.context_processors_data['user'].username == "admin"

        return {
            "variable": kwargs["variable"],
        }

# Access component's HTML / JS / CSS
Table.template
Table.js
Table.css

# Render the component
rendered = Table.render(
    kwargs={"variable": "test", "another": 1},
    args=(123, "str"),
    slots={"footer": "MY_FOOTER"},
)

Use the {% html_attrs %} template tag to render HTML attributes.

It supports:

<div
    {% html_attrs
        attrs
        defaults:class="default-class"
        class="extra-class"
    %}
>

{% html_attrs %} offers a Vue-like granular control for class and style HTML attributes, where you can use a dictionary to manage each class name or style property separately.

{% html_attrs
    class="foo bar"
    class={
        "baz": True,
        "foo": False,
    }
    class="extra"
%}
{% html_attrs
    style="text-align: center; background-color: blue;"
    style={
        "background-color": "green",
        "color": None,
        "width": False,
    }
    style="position: absolute; height: 12px;"
%}

Read more about HTML attributes.

django-components makes integration with HTMX, AlpineJS or jQuery easy by allowing components to be rendered as HTML fragments:

# components/calendar/calendar.py
@register("calendar")
class Calendar(Component):
    template_file = "calendar.html"

    class View:
        # Register Component with `urlpatterns`
        public = True

        # Define handlers
        def get(self, request, *args, **kwargs):
            page = request.GET.get("page", 1)
            return self.component.render_to_response(
                request=request,
                kwargs={
                    "page": page,
                },
            )

    def get_template_data(self, args, kwargs, slots, context):
        return {
            "page": kwargs["page"],
        }

# Get auto-generated URL for the component
url = get_component_url(Calendar)

# Or define explicit URL in urls.py
path("calendar/", Calendar.as_view())

django-components supports the provide / inject pattern, similarly to React's Context Providers or Vue's provide / inject:

Read more about Provide / Inject.

<body>
    {% provide "theme" variant="light" %}
        {% component "header" / %}
    {% endprovide %}
</body>
@register("header")
class Header(Component):
    template = "..."

    def get_template_data(self, args, kwargs, slots, context):
        theme = self.inject("theme").variant
        return {
            "theme": theme,
        }
Input validation and static type hints

Avoid needless errors with type hints and runtime input validation.

To opt-in to input validation, define types for component's args, kwargs, slots, and more:

from typing import NamedTuple, Optional
from django.template import Context
from django_components import Component, Slot, SlotInput

class Button(Component):
    class Args(NamedTuple):
        size: int
        text: str

    class Kwargs(NamedTuple):
        variable: str
        another: int
        maybe_var: Optional[int] = None  # May be omitted

    class Slots(NamedTuple):
        my_slot: Optional[SlotInput] = None
        another_slot: SlotInput

    def get_template_data(self, args: Args, kwargs: Kwargs, slots: Slots, context: Context):
        args.size  # int
        kwargs.variable  # str
        slots.my_slot  # Slot[MySlotData]

To have type hints when calling Button.render() or Button.render_to_response(), wrap the inputs in their respective Args, Kwargs, and Slots classes:

Button.render(
    # Error: First arg must be `int`, got `float`
    args=Button.Args(
        size=1.25,
        text="abc",
    ),
    # Error: Key "another" is missing
    kwargs=Button.Kwargs(
        variable="text",
    ),
)

Django-components functionality can be extended with Extensions. Extensions allow for powerful customization and integrations. They can:

Some of the extensions include:

Some of the planned extensions include:

from django_components import Component

class MyComponent(Component):
    class Cache:
        enabled = True
        ttl = 60 * 60 * 24  # 1 day

        def hash(self, *args, **kwargs):
            return hash(f"{json.dumps(args)}:{json.dumps(kwargs)}")
from django_components.testing import djc_test

from components.my_table import MyTable

@djc_test
def test_my_table():
    rendered = MyTable.render(
        kwargs={
            "title": "My table",
        },
    )
    assert rendered == "<table>My table</table>"

Read the full documentation here.

... or jump right into the code, check out the example project.

Our aim is to be at least as fast as Django templates.

As of 0.130, django-components is ~4x slower than Django templates.

Render time django 68.9±0.6ms django-components 259±4ms

See the full performance breakdown for more information.

Read the Release Notes to see the latest features and fixes.

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.

Contributing and development

Get involved or sponsor this project - See here

Running django-components locally for development - See here


RetroSearch is an open source project built by @garambo | Open a GitHub Issue

Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo

HTML: 3.2 | Encoding: UTF-8 | Version: 0.7.4