Skip to main content

django_slots = inclusion tag + blocks

Project description

django_template_component

django_template_component = inclusion tag + blocks

pip install django-template-component
INSTALLED_APPS = [
    # ...
    
    'django_template_component',
]

Examples

Button example

# app/templatetags/component_tags.py
from django_template_component import Library, Component

register = Library()


@register.component
class Button(Component):
    pass
{# app/templates/components/button.html #}
<button>{{ slot }}</button>

Usage

{% load component_tags %}
{% button %}
    <div>Save</div>
    <small>and add another</small>
{% /button %}

Details example

# app/templatetags/component_tags.py
from django_template_component import Library, Component

register = Library()


@register.block_component
class Details(Component):
    pass
{# app/templates/components/details.html #}
<details>
  <summary>{{ slots.summary }}</summary>
  {{ slot }}
</details>

Usage

{% load component_tags %}
{% load slot_tags %}

{% details %}
    {% slot summary %}the summary{% /slot %}
    the default slot
{% /details %}

Form example

Python

# app/templatetags/component_tags.py
from django.forms.utils import ErrorList
from django.forms import Form

from django_template_component.components import Library, Component, DEFAULT_SLOT_NAME


register = Library()


@register.component
class Button(Component):
    STYLE_CHOICES = ['green', 'red']
    TYPE_CHOICES = ['submit', 'reset', '']

    def get_context_data(
        self, 
        filled_slots: list[str], 
        *,
        type: str = 'submit', 
        name: str ='', 
        value: str = 'Submit', 
        style: str = 'green'
    ):
        if value and DEFAULT_SLOT_NAME in filled_slots:
            raise self.validation_error("use value keyword argument or slot tag.")

        if type not in self.TYPE_CHOICES:
            raise self.validation_error(f"type='{type}' must be one of {self.TYPE_CHOICES!r}")
        
        if style not in self.STYLE_CHOICES:
            raise self.validation_error(f"style='{style}' must be one of {self.STYLE_CHOICES!r}")

        return {
            'type': type,
            'name': name,
            'value': value,
            'style': style,
        }
        

@register.inline_component
class FormErrors(Component):
    def get_context_data(self, filled_slots: list[str], *, errors: ErrorList):
        return {
            'errors': errors,
        }


@register.inline_component
class FormField(Component):
    def get_context_data(self, filled_slots: list[str], *, field):
        return {
            'field': field,
        }


@register.component
class Form(Component):
    def get_context_data(
        self, 
        filled_slots: list[str],
        *,
        form: Form, 
        action: str = '', 
        method: str = 'post', 
        csrf_token: str = '', 
        csrf_exempt: bool = False
    ):
        if csrf_exempt is False and method == 'post' and csrf_token == '':
            raise self.validation_error(
                "csrf_token keyword argument is required when method is post and csrf_exempt is false"
            )
        
        return {
            'form': form,
            'action': action,
            'method': method,
            'csrf_token': csrf_token,
        }

HTML

{# app/templates/components/button.html #}
{% load slot_tags %}
<button {% if type %} type="{{ type }}"{% endif %}{% if name %} name="{{ name }}"{% endif %}
    class="btn{% if style == "green" %} btn--green{% elif style == "red" %}btn--red{% endif %}">
    {% if value %}{{ value }}{% else %}{{ slot }}{% endif %}
</button>
{# app/templates/components/form_errors.html #}
{% if errors %}
<div>
    {% for error in errors %}
    <div>{{ error }}</div>
    {% endfor %}
</div>
{% endif %}
{# app/templates/components/form_field.html #}
{% load component_tags %}
<div class="field">
    {% if field.label %}
        <label for="{{ field.id_for_label }}">{{ field.label }}</label>
    {% endif %}
    {% form_errors/ errors=field.errors %}
    <div>
        {{ field }}
    </div>
    {% if field.help_text %}
        <small>{{ field.help_text }}</small>
    {% endif %}
</div>
{# app/templates/components/form.html #}
{% load component_tags %}
<form action="{{ action }}" method="{{ method }}"{% if form.is_multipart %} enctype="multipart/form-data"{% endif %}>
    {% if csrf_token %}<input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">{% endif %}
    {% for field in form.hidden_fields %}{{ field }}{% endfor %}
    
    {{ slots.hidden_fields }}
        
    {% form_errors/ errors=form.non_field_errors %}
    
    {% if slots.visible_fields %}
        {{ slots.visible_fields }}
    {% else %}
        {% for field in form.visible_fields %}
            {% form_field/ field=field %}
        {% endfor %}
    {% endif %}
    
    {% if slots.buttons %}
        {{ slots.buttons }}
    {% else %}
        {% button/ value=_("Submit") %}
    {% endif %}
</form>

Usage

{% load slot_tags %}
{% load component_tags %}


<!-- inline use -->
{% form/ form=form csrf_token=csrf_token %}

<!-- block use -->
{% form/ form=form csrf_token=csrf_token %}

    <!-- override visible_fields slot in base template -->
    {% slot visible_fields %}
        {% form_field/ field=form.title %}
    {% /slot %}

    <!-- override buttons slot in base template -->
    {% slot buttons %}
        {% button %}Delete{% /button %}
    {% /slot %}
{% /form %}

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

django_slots-0.1.0.tar.gz (6.1 kB view details)

Uploaded Source

Built Distribution

django_slots-0.1.0-py3-none-any.whl (6.0 kB view details)

Uploaded Python 3

File details

Details for the file django_slots-0.1.0.tar.gz.

File metadata

  • Download URL: django_slots-0.1.0.tar.gz
  • Upload date:
  • Size: 6.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.13 CPython/3.10.2 Darwin/21.0.1

File hashes

Hashes for django_slots-0.1.0.tar.gz
Algorithm Hash digest
SHA256 706bccc632fb524a9cec7f63d27cca27d0ec9f14fb736b526eb097cdb745664b
MD5 e106abcd8248859832a3ec18c44bef53
BLAKE2b-256 5c1398185c042f0763bfb0df7f5d7bbf36070fc2dc6974087f2e882eb4571be3

See more details on using hashes here.

File details

Details for the file django_slots-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: django_slots-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 6.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.1.13 CPython/3.10.2 Darwin/21.0.1

File hashes

Hashes for django_slots-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d2aaf34c313f451729428229e499acda24d8857bf6339497563d426b3a3ed18f
MD5 b3c99ffe7c978bc81a8b277e80ba891a
BLAKE2b-256 b9f843bff436fb08c3a0d0d08f987430d869901239834c9c38d9fe6b9a091e0f

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