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
Release history Release notifications | RSS feed
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)
Built Distribution
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
Algorithm | Hash digest | |
---|---|---|
SHA256 | 706bccc632fb524a9cec7f63d27cca27d0ec9f14fb736b526eb097cdb745664b |
|
MD5 | e106abcd8248859832a3ec18c44bef53 |
|
BLAKE2b-256 | 5c1398185c042f0763bfb0df7f5d7bbf36070fc2dc6974087f2e882eb4571be3 |
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
Algorithm | Hash digest | |
---|---|---|
SHA256 | d2aaf34c313f451729428229e499acda24d8857bf6339497563d426b3a3ed18f |
|
MD5 | b3c99ffe7c978bc81a8b277e80ba891a |
|
BLAKE2b-256 | b9f843bff436fb08c3a0d0d08f987430d869901239834c9c38d9fe6b9a091e0f |