django-cotton


Namedjango-cotton JSON
Version 1.5.1 PyPI version JSON
download
home_pageNone
SummaryBringing component based design to Django templates.
upload_time2024-12-06 13:30:26
maintainerNone
docs_urlNone
authorWill Abbott
requires_python<4,>=3.8
licenseMIT
keywords django components ui
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            <img alt="Django Cotton Logo" src="https://github.com/wrabit/django-cotton/assets/5918271/1b0de6be-e943-4250-84c5-4662e2be07f5" width="400">

<!--<img src="https://github.com/wrabit/django-cotton/assets/5918271/e1c204dd-a91d-4883-8b76-b47af264c251" width="400">-->

# Django Cotton

![PyPI](https://img.shields.io/pypi/v/django-cotton?color=blue&style=flat-square)
![PyPI - Downloads](https://img.shields.io/pypi/dm/django-cotton?color=blue&style=flat-square)

Bringing component-based design to Django templates.

- Docs site + demos: <a href="https://django-cotton.com" target="_blank">django-cotton.com</a>

## Contents

[Why?](#why-cotton)  
[Install](#install)  
[Usage Basics](#usage-basics)  
[Your First component](#your-first-component)  
[Attributes](#add-attributes)  
[Named Slots](#named-slots)  
[Pass Template Variables](#pass-template-variable-as-an-attribute)  
[Template expressions in attributes](#template-expressions-inside-attributes)  
[Boolean attributes](#boolean-attributes)  
[Passing Python data types](#passing-python-data-types)  
[Increase Re-usability with `{{ attrs }}`](#increase-re-usability-with--attrs-)  
[In-component Variables with `<c-vars>`](#in-component-variables-with-c-vars)  
[HTMX Example](#an-example-with-htmx)  
[Limitations in Django that Cotton overcomes](#limitations-in-django-that-cotton-overcomes)  
[Configuration](#configuration)  
[Caching](#caching)  
[Version support](#version-support)  
[Changelog](#changelog)  
[Comparison with other packages](#comparison-with-other-packages)  

<hr>

## Why Cotton?

Cotton aims to overcome [certain limitations](#limitations-in-django-that-cotton-overcomes) that exist in the django template system that hold us back when we want to apply modern practices to compose UIs in a modular and reusable way.

## Key Features
- **Modern UI Composition:** Efficiently compose and reuse UI components.
- **Interoperable with Django:** Cotton only enhances django's existing template system (no Jinja needed).
- **HTML-like Syntax:** Better code editor support and productivity as component tags are similar to html tags.
- **Minimal Overhead:** Compiles to native Django components with dynamic caching.
- **Encapsulates UI:** Keep layout, design and interaction in one file (especially when paired with Tailwind and Alpine.js)
- **Compliments HTMX:** Create smart components, reducing repetition and enhancing maintainability.

<hr>

## Install

```bash
pip install django-cotton
```

### settings.py

```python
INSTALLED_APPS = [
    'django_cotton'
]
```

If you have previously specified a custom loader, you should perform [manual setup](https://django-cotton.com/docs/quickstart#install).

## Usage Basics
- **Component Placement:** Components should be placed in the `templates/cotton` folder (or define a [custom folder](https://django-cotton.com/docs/configuration)).
- **Naming Conventions:** 
  - Component filenames use snake_case: `my_component.html`
  - Components are called using kebab-case prefixed by 'c-': `<c-my-component />`

<hr>

## Walkthrough

### Your first component

```html
<!-- cotton/button.html -->
<a href="/" class="...">{{ slot }}</a>
```
```html
<!-- in view -->
<c-button>Contact</c-button>
```
```html
<!-- html output -->
<a href="/" class="...">Contact</a>
```

Everything provided between the opening and closing tag is provided to the component as `{{ slot }}`. It can contain any content, HTML or Django template expression.

### Adding attributes

```html
<!-- cotton/button.html -->
<a href="{{ url }}" class="...">
    {{ slot }}
</a>
```
```html
<!-- in view -->
<c-button url="/contact">Contact</c-button>
```
```html
<!-- html output -->
<a href="/contact" class="...">
    Contact
</a>
```

### Named slots

Named slots are a powerful concept. They allow us to provide HTML to appear in one or more areas in the component. Here we allow the button to optionally display an svg icon: 

```html
<!-- cotton/button.html -->
<a href="{{ url }}" class="...">
    {{ slot }}
  
    {% if icon %} 
        {{ icon }} 
    {% endif %}
</a>
```
```html
<!-- in view -->
<c-button url="/contact">
    Contact
    <c-slot name="icon">
        <svg>...</svg>
    </c-slot>
</c-button>
```

Named slots can also contain any django native template logic:

```html
<!-- in view -->
<c-button url="/contact">
    <c-slot name="icon">
      {% if mode == 'edit' %}
          <svg id="pencil">...</svg>
      {% else %}
          <svg id="disk">...</svg>
      {% endif %}
    </c-slot>
</c-button>
```

### Pass template variable as an attribute

To pass a template variable you prepend the attribute name with a colon `:`. Consider a bio card component:

```html
<!-- in view -->
<c-bio-card :user="user" />
```

That has a component definition like:

```html
<!-- cotton/bio_card.html -->
<div class="...">
  <img src="{{ user.avatar }}" alt="...">
  {{ user.username }} {{ user.country_code }}
</div>
```


### Template expressions inside attributes

You can use template expression statements inside attributes.

```html
<c-weather icon="fa-{{ icon }}"
           unit="{{ unit|default:'c' }}"
           condition="very {% get_intensity %}"
/>
```

### Boolean attributes

Boolean attributes reduce boilerplate when we just want to indicate a certain attribute should be `True` or not.

```html
<!-- in view -->
<c-button url="/contact" external>Contact</c-button>
```
By passing just the attribute name without a value, it will automatically be provided to the component as `True`

```html
<!-- cotton/button.html -->
<a href="{{ url }}" {% if external %} target="_blank" {% endif %} class="...">
    {{ slot }}
</a>
```

### Passing Python data types

Using the ':' to prefix an attribute tells Cotton we're passing a dynamic type down. We already know we can use this to send a variable, but you can also send basic python types, namely:

- Integers and Floats
- None, True and False
- Lists
- Dictionaries

This benefits a number of use-cases, for example if you have a select component that you want to provide the possible options from the parent:

```html
<!-- cotton/select.html -->
<select {{ attrs }}>
    {% for option in options %}
        <option value="{{ option }}">{{ option }}</option>
    {% endfor %}
</select>
```

```html
<c-select name="q1" :options="['yes', 'no', 'maybe']" />
```

```html
<!-- source code output -->
<select name="q1">
    <option value="yes">yes</option>
    <option value="no">no</option>
    <option value="maybe">maybe</option>
</select>
```

### Increase Re-usability with `{{ attrs }}`

`{{ attrs }}` is a special variable that contains all the attributes passed to the component in an key="value" format. This is useful when you want to pass all attributes to a child element without having to explicitly define them in the component template. For example, you have inputs that can have any number of attributes defined:

```html
<!-- cotton/input.html -->
<input type="text" class="..." {{ attrs }} />
```

```html
<!-- example usage -->
<c-input placeholder="Enter your name" />
<c-input name="country" id="country" value="Japan" required />
```

```html
<!-- html output -->
<input type="text" class="..." placeholder="Enter your name" />
<input type="text" class="..." name="country" id="country" value="Japan" required />
```

### In-component Variables with `<c-vars>`

Django templates adhere quite strictly to the MVC model and does not permit a lot of data manipulation in views. Fair enough, but what if we want to handle data for the purpose of UI state only? Having presentation related variables defined in the back is overkill and can quickly lead to higher maintenance cost and loses encapsulation of the component. Cotton allows you define in-component variables for the following reasons:

#### Using `<c-vars>` for default attributes

In this example we have a button component with a default "theme" but it can be overridden.

```html
<!-- cotton/button.html -->
<c-vars theme="bg-purple-500" />

<a href="..." class="{{ theme }}">
    {{ slot }}
</a>
```
```html
<!-- in view -->
<c-button>I'm a purple button</c-button>
```
```html
<!-- html output -->
<a href="..." class="bg-purple-500">
    I'm a purple button
</a>
```

Now we have a default theme for our button, but it is overridable:

```html
<!-- in view -->
<c-button theme="bg-green-500">But I'm green</c-button>
```
```html
<!-- html output -->
<a href="..." class="bg-green-500">
    But I'm green
</a>
```

#### Using `<c-vars>` to govern `{{ attrs }}`

Using `{{ attrs }}` to pass all attributes from parent scope onto an element in the component, you'll sometimes want to provide additional properties to the component which are not intended to be an attributes. In this case you can declare them in `<c-vars />` and it will prevent it from being in `{{ attrs }}`

Take this example where we want to provide any number of attributes to an input but also an icon setting which is not intened to be an attribute on `<input>`:

```html
<!-- in view -->
<c-input type="password" id="password" icon="padlock" />
```
```html
<!-- cotton/input.html -->
<c-vars icon />

<img src="icons/{{ icon }}.png" />

<input {{ attrs }} />
```

Input will have all attributes provided apart from the `icon`:

```html
<input type="password" id="password" />
```

### Dynamic Components

Sometimes there is a need to include a component dynamically, for example, you are looping through some data and the type of component is defined within a variable.

```html
<!--
form_fields = [
  {'type': 'text'},
  {'type': 'textarea'},
  {'type': 'checkbox'}  
]
-->

{% for field in form_fields %}
    <c-component :is="field.type" />
{% endfor %}
```

You can also provide a template expression, should the component be inside a subdirectory or have a prefix:

```html
{% for field in form_fields %}
    <!-- subfolder -->
    <c-component is="form-fields.{{ field.type }}" />

    <!-- component prefix -->
    <c-component is="field_{{ field.type }}" />
{% endfor %}
```

<hr>

### An example with HTMX

Cotton helps carve out re-usable components, here we show how to make a re-usable form, reducing code repetition and improving maintainability:

```html
<!-- cotton/form.html -->
<div id="result" class="..."></div>

<form {{ attrs }} hx-target="#result" hx-swap="outerHTML">
    {{ slot }}
    <button type="submit">Submit</button>
</form>
```

```html
<!-- in view -->
<c-form hx-post="/contact">
    <input type="text" name="name" placeholder="Name" />
    <input type="text" name="email" placeholder="Email" />
    <input type="checkbox" name="signup" />
</c-form>

<c-form hx-post="/buy">
    <input type="text" name="type" />
    <input type="text" name="quantity" />
</c-form>
```

<hr>

## Limitations in Django that Cotton overcomes

Whilst you _can_ build frontends with Django’s native tags, there are a few things that hold us back when we want to apply modern practices:

### `{% block %}` and `{% extends %}`
This system strongly couples child and parent templates making it hard to create a truly re-usable component that can be used in places without it having a related base template.

### What about `{% include %}` ?
Modern libraries allow components to be highly configurable, whether it’s by attributes, passing variables, passing HTML with default and named slots. {% include %} tags, whilst they have the ability to pass simple variables and text, they will not allow you to easily send HTML blocks with template expressions let alone other niceties such as boolean attributes, named slots etc.

### What's with `{% with %}`?
Whilst {% with %} tags allow us to provide variables and strings it quickly busies up your code and has the same limitations about passing more complex types.

### Custom `{% templatetags %}`
Cotton does essentially compile down to templatetags but there is some extra work it performs above it to help with scoping and auto-managing keys which will be difficult to manage manually in complex nested structures.

<a href="https://medium.com/@willabbott/introducing-django-cotton-revolutionizing-ui-composition-in-django-ea7fe06156b0" target="_blank">[Source article]</a>

## Native Django template tags vs Cotton

In addition, Cotton enables you to navigate around some of the limitations with Django's native tags and template language:

### HTML in attributes
❌ **Django native:**
```html
{% my_component header="<h1>Header</h1>" %}
```
✅ **Cotton:**
```html
<c-my-component>
    <c-slot name="header">
        <h1>Header</h1>
    </c-slot>
</c-my-component>
```

### Template expressions in attributes
❌ **Django native:**
```html
{% my_component model="todos.{{ index }}.name" extra="{% get_extra %}" %}
```
✅ **Cotton:**
```html
<c-my-component model="todos.{{ index }}.name" extra="{% get_extra %} />
```

### Pass simple python types
❌ **Django native:**
```html
{% my_component default_options="['yes', 'no', 'maybe']" %}
{% my_component config="{'open': True}" %}
```
✅ **Cotton:**
```html
<c-my-component :default_options="['yes', 'no', 'maybe']" />
<c-my-component :config="{'open': True}" />

(provides a List and Dict to component)
```

### Multi-line definitions
❌ **Django native:** 
```html
{% my_component
    arg=1 %}
```
✅ **Cotton:**
```html
<c-my-component
    class="blue"
    x-data="{
        something: 1
    }" />
```

### Dynamic components
❌ **Django native:** 
```html
{% {{ templatetag_name }} arg=1 %}
```
✅ **Cotton:**
```html
<c-component :is="component_name" />
<c-component is="{{ component_name }}" />
<c-component is="subfolder1.subfolder2.{{ component_name }}" />
```

<hr>

## Configuration

`COTTON_DIR` (default: "cotton")  

The directory where your components are stored.

`COTTON_BASE_DIR` (default: None)  

If you use a project-level templates folder then you can set the path here. This is not needed if your project already has a `BASE_DIR` variable.

`COTTON_SNAKE_CASED_NAMES` (default: True)  

Whether to search for component filenames in snake_case. If set to False, you can use kebab-cased / hyphenated filenames.

<hr>

## Caching

Cotton is optimal when used with Django's cached.Loader. If you use <a href="https://django-cotton.com/docs/quickstart">automatic configuration</a> then the cached loader will be automatically applied.

<hr>

## Version Support

- Python >= 3.8
- Django >4.2,<5.2

<hr>

## Changelog

[See releases](https://github.com/wrabit/django-cotton/releases)

<hr>

## Comparison with other packages

| **Feature**                                                                                         | **Cotton**                 | **django-components**                  | **Slippers**                                               |
|-----------------------------------------------------------------------------------------------------|----------------------------|----------------------------------------|------------------------------------------------------------|
| **Intro**                                                                                           | UI-focused, expressive syntax       | Holistic solution with backend logic   | Enhances DTL for reusable components                       |
| **Definition of ‘component’**                                                                       | An HTML template           | A backend class with template          | An HTML template                                           |
| **Syntax Style**                                                                                     | HTML-like                  | Django Template Tags                   | Django Template Tags with custom tags                      |
| **One-step package install**                                                                        | ✅                        | ❌                                    | ❌                                                        |
| **Create component in one step?**                                                                   | ✅ <br> (place in folder) | ✅ <br> (Technically yes with single-file components) | ❌ <br> (need to register in YAML file or with function)   |
| **Slots** <br> Pass HTML content between tags                                             | ✅                        | ✅                                    | ✅                                                        |
| **Named Slots** <br> Designate a slot in the component template                                     | ✅                        | ✅                                    | ✅ (using ‘fragments’)                                      |
| **Dynamic Components** <br> Dynamically render components based on a variable or expression         | ✅                        | ✅                                    | ❌                                                        |
| **Scoped Slots** <br> Reference component context in parent template                                | ❌                         | ✅                                    | ❌                                                         |
| **Dynamic Attributes** <br> Pass string literals of basic Python types                              | ✅                        | ❌                                    | ❌                                                         |
| **Boolean Attributes** <br> Pass valueless attributes as True                                       | ✅                        | ✅                                    | ❌                                                         |
| **Implicit Attribute Passing** <br> Pass all defined attributes to an element                       | ✅                        | ❌                                     | ✅                                                        |
| **Django Template Expressions in Attribute Values** <br> Use template expressions in attribute values | ✅                        | ❌                                    | ❌                                                         |
| **Attribute Merging** <br> Replace existing attributes with component attributes                    | ✅                        | ✅                                    | ❌                                                         |
| **Multi-line Component Tags** <br> Write component tags over multiple lines                         | ✅                        | ✅                                     | ❌                                                         |

**Notes:** 

- Some features here can be resolved with 3rd party plugins, for example for expressions, you can use something like `django-expr` package. So the list focuses on a comparison of core feature of that library.

<hr>

For full docs and demos, checkout <a href="https://django-cotton.com" target="_blank">django-cotton.com</a>

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "django-cotton",
    "maintainer": null,
    "docs_url": null,
    "requires_python": "<4,>=3.8",
    "maintainer_email": null,
    "keywords": "django, components, ui",
    "author": "Will Abbott",
    "author_email": "willabb83@gmail.com",
    "download_url": "https://files.pythonhosted.org/packages/29/2d/c6b89fed969720f180b2205f455212e71a7e6205d5c84992d82ddee1768c/django_cotton-1.5.1.tar.gz",
    "platform": null,
    "description": "<img alt=\"Django Cotton Logo\" src=\"https://github.com/wrabit/django-cotton/assets/5918271/1b0de6be-e943-4250-84c5-4662e2be07f5\" width=\"400\">\n\n<!--<img src=\"https://github.com/wrabit/django-cotton/assets/5918271/e1c204dd-a91d-4883-8b76-b47af264c251\" width=\"400\">-->\n\n# Django Cotton\n\n![PyPI](https://img.shields.io/pypi/v/django-cotton?color=blue&style=flat-square)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/django-cotton?color=blue&style=flat-square)\n\nBringing component-based design to Django templates.\n\n- Docs site + demos: <a href=\"https://django-cotton.com\" target=\"_blank\">django-cotton.com</a>\n\n## Contents\n\n[Why?](#why-cotton)  \n[Install](#install)  \n[Usage Basics](#usage-basics)  \n[Your First component](#your-first-component)  \n[Attributes](#add-attributes)  \n[Named Slots](#named-slots)  \n[Pass Template Variables](#pass-template-variable-as-an-attribute)  \n[Template expressions in attributes](#template-expressions-inside-attributes)  \n[Boolean attributes](#boolean-attributes)  \n[Passing Python data types](#passing-python-data-types)  \n[Increase Re-usability with `{{ attrs }}`](#increase-re-usability-with--attrs-)  \n[In-component Variables with `<c-vars>`](#in-component-variables-with-c-vars)  \n[HTMX Example](#an-example-with-htmx)  \n[Limitations in Django that Cotton overcomes](#limitations-in-django-that-cotton-overcomes)  \n[Configuration](#configuration)  \n[Caching](#caching)  \n[Version support](#version-support)  \n[Changelog](#changelog)  \n[Comparison with other packages](#comparison-with-other-packages)  \n\n<hr>\n\n## Why Cotton?\n\nCotton aims to overcome [certain limitations](#limitations-in-django-that-cotton-overcomes) that exist in the django template system that hold us back when we want to apply modern practices to compose UIs in a modular and reusable way.\n\n## Key Features\n- **Modern UI Composition:** Efficiently compose and reuse UI components.\n- **Interoperable with Django:** Cotton only enhances django's existing template system (no Jinja needed).\n- **HTML-like Syntax:** Better code editor support and productivity as component tags are similar to html tags.\n- **Minimal Overhead:** Compiles to native Django components with dynamic caching.\n- **Encapsulates UI:** Keep layout, design and interaction in one file (especially when paired with Tailwind and Alpine.js)\n- **Compliments HTMX:** Create smart components, reducing repetition and enhancing maintainability.\n\n<hr>\n\n## Install\n\n```bash\npip install django-cotton\n```\n\n### settings.py\n\n```python\nINSTALLED_APPS = [\n    'django_cotton'\n]\n```\n\nIf you have previously specified a custom loader, you should perform [manual setup](https://django-cotton.com/docs/quickstart#install).\n\n## Usage Basics\n- **Component Placement:** Components should be placed in the `templates/cotton` folder (or define a [custom folder](https://django-cotton.com/docs/configuration)).\n- **Naming Conventions:** \n  - Component filenames use snake_case: `my_component.html`\n  - Components are called using kebab-case prefixed by 'c-': `<c-my-component />`\n\n<hr>\n\n## Walkthrough\n\n### Your first component\n\n```html\n<!-- cotton/button.html -->\n<a href=\"/\" class=\"...\">{{ slot }}</a>\n```\n```html\n<!-- in view -->\n<c-button>Contact</c-button>\n```\n```html\n<!-- html output -->\n<a href=\"/\" class=\"...\">Contact</a>\n```\n\nEverything provided between the opening and closing tag is provided to the component as `{{ slot }}`. It can contain any content, HTML or Django template expression.\n\n### Adding attributes\n\n```html\n<!-- cotton/button.html -->\n<a href=\"{{ url }}\" class=\"...\">\n    {{ slot }}\n</a>\n```\n```html\n<!-- in view -->\n<c-button url=\"/contact\">Contact</c-button>\n```\n```html\n<!-- html output -->\n<a href=\"/contact\" class=\"...\">\n    Contact\n</a>\n```\n\n### Named slots\n\nNamed slots are a powerful concept. They allow us to provide HTML to appear in one or more areas in the component. Here we allow the button to optionally display an svg icon: \n\n```html\n<!-- cotton/button.html -->\n<a href=\"{{ url }}\" class=\"...\">\n    {{ slot }}\n  \n    {% if icon %} \n        {{ icon }} \n    {% endif %}\n</a>\n```\n```html\n<!-- in view -->\n<c-button url=\"/contact\">\n    Contact\n    <c-slot name=\"icon\">\n        <svg>...</svg>\n    </c-slot>\n</c-button>\n```\n\nNamed slots can also contain any django native template logic:\n\n```html\n<!-- in view -->\n<c-button url=\"/contact\">\n    <c-slot name=\"icon\">\n      {% if mode == 'edit' %}\n          <svg id=\"pencil\">...</svg>\n      {% else %}\n          <svg id=\"disk\">...</svg>\n      {% endif %}\n    </c-slot>\n</c-button>\n```\n\n### Pass template variable as an attribute\n\nTo pass a template variable you prepend the attribute name with a colon `:`. Consider a bio card component:\n\n```html\n<!-- in view -->\n<c-bio-card :user=\"user\" />\n```\n\nThat has a component definition like:\n\n```html\n<!-- cotton/bio_card.html -->\n<div class=\"...\">\n  <img src=\"{{ user.avatar }}\" alt=\"...\">\n  {{ user.username }} {{ user.country_code }}\n</div>\n```\n\n\n### Template expressions inside attributes\n\nYou can use template expression statements inside attributes.\n\n```html\n<c-weather icon=\"fa-{{ icon }}\"\n           unit=\"{{ unit|default:'c' }}\"\n           condition=\"very {% get_intensity %}\"\n/>\n```\n\n### Boolean attributes\n\nBoolean attributes reduce boilerplate when we just want to indicate a certain attribute should be `True` or not.\n\n```html\n<!-- in view -->\n<c-button url=\"/contact\" external>Contact</c-button>\n```\nBy passing just the attribute name without a value, it will automatically be provided to the component as `True`\n\n```html\n<!-- cotton/button.html -->\n<a href=\"{{ url }}\" {% if external %} target=\"_blank\" {% endif %} class=\"...\">\n    {{ slot }}\n</a>\n```\n\n### Passing Python data types\n\nUsing the ':' to prefix an attribute tells Cotton we're passing a dynamic type down. We already know we can use this to send a variable, but you can also send basic python types, namely:\n\n- Integers and Floats\n- None, True and False\n- Lists\n- Dictionaries\n\nThis benefits a number of use-cases, for example if you have a select component that you want to provide the possible options from the parent:\n\n```html\n<!-- cotton/select.html -->\n<select {{ attrs }}>\n    {% for option in options %}\n        <option value=\"{{ option }}\">{{ option }}</option>\n    {% endfor %}\n</select>\n```\n\n```html\n<c-select name=\"q1\" :options=\"['yes', 'no', 'maybe']\" />\n```\n\n```html\n<!-- source code output -->\n<select name=\"q1\">\n    <option value=\"yes\">yes</option>\n    <option value=\"no\">no</option>\n    <option value=\"maybe\">maybe</option>\n</select>\n```\n\n### Increase Re-usability with `{{ attrs }}`\n\n`{{ attrs }}` is a special variable that contains all the attributes passed to the component in an key=\"value\" format. This is useful when you want to pass all attributes to a child element without having to explicitly define them in the component template. For example, you have inputs that can have any number of attributes defined:\n\n```html\n<!-- cotton/input.html -->\n<input type=\"text\" class=\"...\" {{ attrs }} />\n```\n\n```html\n<!-- example usage -->\n<c-input placeholder=\"Enter your name\" />\n<c-input name=\"country\" id=\"country\" value=\"Japan\" required />\n```\n\n```html\n<!-- html output -->\n<input type=\"text\" class=\"...\" placeholder=\"Enter your name\" />\n<input type=\"text\" class=\"...\" name=\"country\" id=\"country\" value=\"Japan\" required />\n```\n\n### In-component Variables with `<c-vars>`\n\nDjango templates adhere quite strictly to the MVC model and does not permit a lot of data manipulation in views. Fair enough, but what if we want to handle data for the purpose of UI state only? Having presentation related variables defined in the back is overkill and can quickly lead to higher maintenance cost and loses encapsulation of the component. Cotton allows you define in-component variables for the following reasons:\n\n#### Using `<c-vars>` for default attributes\n\nIn this example we have a button component with a default \"theme\" but it can be overridden.\n\n```html\n<!-- cotton/button.html -->\n<c-vars theme=\"bg-purple-500\" />\n\n<a href=\"...\" class=\"{{ theme }}\">\n    {{ slot }}\n</a>\n```\n```html\n<!-- in view -->\n<c-button>I'm a purple button</c-button>\n```\n```html\n<!-- html output -->\n<a href=\"...\" class=\"bg-purple-500\">\n    I'm a purple button\n</a>\n```\n\nNow we have a default theme for our button, but it is overridable:\n\n```html\n<!-- in view -->\n<c-button theme=\"bg-green-500\">But I'm green</c-button>\n```\n```html\n<!-- html output -->\n<a href=\"...\" class=\"bg-green-500\">\n    But I'm green\n</a>\n```\n\n#### Using `<c-vars>` to govern `{{ attrs }}`\n\nUsing `{{ attrs }}` to pass all attributes from parent scope onto an element in the component, you'll sometimes want to provide additional properties to the component which are not intended to be an attributes. In this case you can declare them in `<c-vars />` and it will prevent it from being in `{{ attrs }}`\n\nTake this example where we want to provide any number of attributes to an input but also an icon setting which is not intened to be an attribute on `<input>`:\n\n```html\n<!-- in view -->\n<c-input type=\"password\" id=\"password\" icon=\"padlock\" />\n```\n```html\n<!-- cotton/input.html -->\n<c-vars icon />\n\n<img src=\"icons/{{ icon }}.png\" />\n\n<input {{ attrs }} />\n```\n\nInput will have all attributes provided apart from the `icon`:\n\n```html\n<input type=\"password\" id=\"password\" />\n```\n\n### Dynamic Components\n\nSometimes there is a need to include a component dynamically, for example, you are looping through some data and the type of component is defined within a variable.\n\n```html\n<!--\nform_fields = [\n  {'type': 'text'},\n  {'type': 'textarea'},\n  {'type': 'checkbox'}  \n]\n-->\n\n{% for field in form_fields %}\n    <c-component :is=\"field.type\" />\n{% endfor %}\n```\n\nYou can also provide a template expression, should the component be inside a subdirectory or have a prefix:\n\n```html\n{% for field in form_fields %}\n    <!-- subfolder -->\n    <c-component is=\"form-fields.{{ field.type }}\" />\n\n    <!-- component prefix -->\n    <c-component is=\"field_{{ field.type }}\" />\n{% endfor %}\n```\n\n<hr>\n\n### An example with HTMX\n\nCotton helps carve out re-usable components, here we show how to make a re-usable form, reducing code repetition and improving maintainability:\n\n```html\n<!-- cotton/form.html -->\n<div id=\"result\" class=\"...\"></div>\n\n<form {{ attrs }} hx-target=\"#result\" hx-swap=\"outerHTML\">\n    {{ slot }}\n    <button type=\"submit\">Submit</button>\n</form>\n```\n\n```html\n<!-- in view -->\n<c-form hx-post=\"/contact\">\n    <input type=\"text\" name=\"name\" placeholder=\"Name\" />\n    <input type=\"text\" name=\"email\" placeholder=\"Email\" />\n    <input type=\"checkbox\" name=\"signup\" />\n</c-form>\n\n<c-form hx-post=\"/buy\">\n    <input type=\"text\" name=\"type\" />\n    <input type=\"text\" name=\"quantity\" />\n</c-form>\n```\n\n<hr>\n\n## Limitations in Django that Cotton overcomes\n\nWhilst you _can_ build frontends with Django\u2019s native tags, there are a few things that hold us back when we want to apply modern practices:\n\n### `{% block %}` and `{% extends %}`\nThis system strongly couples child and parent templates making it hard to create a truly re-usable component that can be used in places without it having a related base template.\n\n### What about `{% include %}` ?\nModern libraries allow components to be highly configurable, whether it\u2019s by attributes, passing variables, passing HTML with default and named slots. {% include %} tags, whilst they have the ability to pass simple variables and text, they will not allow you to easily send HTML blocks with template expressions let alone other niceties such as boolean attributes, named slots etc.\n\n### What's with `{% with %}`?\nWhilst {% with %} tags allow us to provide variables and strings it quickly busies up your code and has the same limitations about passing more complex types.\n\n### Custom `{% templatetags %}`\nCotton does essentially compile down to templatetags but there is some extra work it performs above it to help with scoping and auto-managing keys which will be difficult to manage manually in complex nested structures.\n\n<a href=\"https://medium.com/@willabbott/introducing-django-cotton-revolutionizing-ui-composition-in-django-ea7fe06156b0\" target=\"_blank\">[Source article]</a>\n\n## Native Django template tags vs Cotton\n\nIn addition, Cotton enables you to navigate around some of the limitations with Django's native tags and template language:\n\n### HTML in attributes\n\u274c **Django native:**\n```html\n{% my_component header=\"<h1>Header</h1>\" %}\n```\n\u2705 **Cotton:**\n```html\n<c-my-component>\n    <c-slot name=\"header\">\n        <h1>Header</h1>\n    </c-slot>\n</c-my-component>\n```\n\n### Template expressions in attributes\n\u274c **Django native:**\n```html\n{% my_component model=\"todos.{{ index }}.name\" extra=\"{% get_extra %}\" %}\n```\n\u2705 **Cotton:**\n```html\n<c-my-component model=\"todos.{{ index }}.name\" extra=\"{% get_extra %} />\n```\n\n### Pass simple python types\n\u274c **Django native:**\n```html\n{% my_component default_options=\"['yes', 'no', 'maybe']\" %}\n{% my_component config=\"{'open': True}\" %}\n```\n\u2705 **Cotton:**\n```html\n<c-my-component :default_options=\"['yes', 'no', 'maybe']\" />\n<c-my-component :config=\"{'open': True}\" />\n\n(provides a List and Dict to component)\n```\n\n### Multi-line definitions\n\u274c **Django native:** \n```html\n{% my_component\n    arg=1 %}\n```\n\u2705 **Cotton:**\n```html\n<c-my-component\n    class=\"blue\"\n    x-data=\"{\n        something: 1\n    }\" />\n```\n\n### Dynamic components\n\u274c **Django native:** \n```html\n{% {{ templatetag_name }} arg=1 %}\n```\n\u2705 **Cotton:**\n```html\n<c-component :is=\"component_name\" />\n<c-component is=\"{{ component_name }}\" />\n<c-component is=\"subfolder1.subfolder2.{{ component_name }}\" />\n```\n\n<hr>\n\n## Configuration\n\n`COTTON_DIR` (default: \"cotton\")  \n\nThe directory where your components are stored.\n\n`COTTON_BASE_DIR` (default: None)  \n\nIf you use a project-level templates folder then you can set the path here. This is not needed if your project already has a `BASE_DIR` variable.\n\n`COTTON_SNAKE_CASED_NAMES` (default: True)  \n\nWhether to search for component filenames in snake_case. If set to False, you can use kebab-cased / hyphenated filenames.\n\n<hr>\n\n## Caching\n\nCotton is optimal when used with Django's cached.Loader. If you use <a href=\"https://django-cotton.com/docs/quickstart\">automatic configuration</a> then the cached loader will be automatically applied.\n\n<hr>\n\n## Version Support\n\n- Python >= 3.8\n- Django >4.2,<5.2\n\n<hr>\n\n## Changelog\n\n[See releases](https://github.com/wrabit/django-cotton/releases)\n\n<hr>\n\n## Comparison with other packages\n\n| **Feature**                                                                                         | **Cotton**                 | **django-components**                  | **Slippers**                                               |\n|-----------------------------------------------------------------------------------------------------|----------------------------|----------------------------------------|------------------------------------------------------------|\n| **Intro**                                                                                           | UI-focused, expressive syntax       | Holistic solution with backend logic   | Enhances DTL for reusable components                       |\n| **Definition of \u2018component\u2019**                                                                       | An HTML template           | A backend class with template          | An HTML template                                           |\n| **Syntax Style**                                                                                     | HTML-like                  | Django Template Tags                   | Django Template Tags with custom tags                      |\n| **One-step package install**                                                                        | \u2705                        | \u274c                                    | \u274c                                                        |\n| **Create component in one step?**                                                                   | \u2705 <br> (place in folder) | \u2705 <br> (Technically yes with single-file components) | \u274c <br> (need to register in YAML file or with function)   |\n| **Slots** <br> Pass HTML content between tags                                             | \u2705                        | \u2705                                    | \u2705                                                        |\n| **Named Slots** <br> Designate a slot in the component template                                     | \u2705                        | \u2705                                    | \u2705 (using \u2018fragments\u2019)                                      |\n| **Dynamic Components** <br> Dynamically render components based on a variable or expression         | \u2705                        | \u2705                                    | \u274c                                                        |\n| **Scoped Slots** <br> Reference component context in parent template                                | \u274c                         | \u2705                                    | \u274c                                                         |\n| **Dynamic Attributes** <br> Pass string literals of basic Python types                              | \u2705                        | \u274c                                    | \u274c                                                         |\n| **Boolean Attributes** <br> Pass valueless attributes as True                                       | \u2705                        | \u2705                                    | \u274c                                                         |\n| **Implicit Attribute Passing** <br> Pass all defined attributes to an element                       | \u2705                        | \u274c                                     | \u2705                                                        |\n| **Django Template Expressions in Attribute Values** <br> Use template expressions in attribute values | \u2705                        | \u274c                                    | \u274c                                                         |\n| **Attribute Merging** <br> Replace existing attributes with component attributes                    | \u2705                        | \u2705                                    | \u274c                                                         |\n| **Multi-line Component Tags** <br> Write component tags over multiple lines                         | \u2705                        | \u2705                                     | \u274c                                                         |\n\n**Notes:** \n\n- Some features here can be resolved with 3rd party plugins, for example for expressions, you can use something like `django-expr` package. So the list focuses on a comparison of core feature of that library.\n\n<hr>\n\nFor full docs and demos, checkout <a href=\"https://django-cotton.com\" target=\"_blank\">django-cotton.com</a>\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Bringing component based design to Django templates.",
    "version": "1.5.1",
    "project_urls": null,
    "split_keywords": [
        "django",
        " components",
        " ui"
    ],
    "urls": [
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "831a0e44ec291ac6c3355ade01da77e4787e35bf10844a495cb12db5dbfc667b",
                "md5": "76ec055327ef2354c917308eccd4fcd0",
                "sha256": "fab92c8d85146f96106ba1c0a36eb7a1bb19fd836bb679a1d25d22ff85cdda3d"
            },
            "downloads": -1,
            "filename": "django_cotton-1.5.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "76ec055327ef2354c917308eccd4fcd0",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": "<4,>=3.8",
            "size": 20439,
            "upload_time": "2024-12-06T13:30:24",
            "upload_time_iso_8601": "2024-12-06T13:30:24.359140Z",
            "url": "https://files.pythonhosted.org/packages/83/1a/0e44ec291ac6c3355ade01da77e4787e35bf10844a495cb12db5dbfc667b/django_cotton-1.5.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": "",
            "digests": {
                "blake2b_256": "292dc6b89fed969720f180b2205f455212e71a7e6205d5c84992d82ddee1768c",
                "md5": "18859e7af4ccd7ff24d8e26e409fcf9f",
                "sha256": "e758729ccb415fff9a1d6fe94e81cd1392ab91fc7ea7b0835995848eb5ea4920"
            },
            "downloads": -1,
            "filename": "django_cotton-1.5.1.tar.gz",
            "has_sig": false,
            "md5_digest": "18859e7af4ccd7ff24d8e26e409fcf9f",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": "<4,>=3.8",
            "size": 21292,
            "upload_time": "2024-12-06T13:30:26",
            "upload_time_iso_8601": "2024-12-06T13:30:26.042598Z",
            "url": "https://files.pythonhosted.org/packages/29/2d/c6b89fed969720f180b2205f455212e71a7e6205d5c84992d82ddee1768c/django_cotton-1.5.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2024-12-06 13:30:26",
    "github": false,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "lcname": "django-cotton"
}
        
Elapsed time: 1.68961s