# paper-forms
This library provides tools to simplify and customize the form rendering process in Django.
It includes the `BaseComposer` class for centralized management of form settings and extends
the functionality of `BoundField` for convenient customization of form fields.
[](https://pypi.org/project/paper-forms/)
[](https://github.com/dldevinc/paper-forms)
[](https://pypi.org/project/paper-forms/)
### Compatibility
- `python` >= 3.9
- `django` >= 3.2
### Features
- [Jinja2](https://jinja.palletsprojects.com/) support.
- [django-jinja](https://github.com/niwinz/django-jinja) support.
## Table of Contents
1. [Installation](#Installation)
2. [Basic Usage](#Basic-Usage)
3. [Composer Configuration](#Composer-Configuration)
1. [Specifying Custom Template Names](#Specifying-Custom-Template-Names)
2. [Customizing Form Field Rendering in Composer](#Customizing-Form-Field-Rendering-in-Composer)
3. [Customizing Composer Class](#Customizing-Composer-Class)
4. [Template Tags](#Template-Tags)
5. [Common Issues and Workarounds](#Common-Issues-and-Workarounds)
## Installation
To get started with `paper-forms`, you need to install the library using `pip`.
Ensure you have Python 3.9 or later installed in your environment.
```shell
pip install paper-forms
```
Next, add "paper_forms" to the `INSTALLED_APPS` in your Django project's `settings.py`:
```python
INSTALLED_APPS = (
# ...
"paper_forms",
)
```
## Basic Usage
Start by creating a simple Django form. No mixins or third-party classes are required.
Just define your form as you normally would using Django's `forms` module.
```python
# forms.py
from django import forms
class ExampleForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField()
```
Now, let's render the form in your template using the `{% field %}` template tag
provided by `paper-forms`. This tag allows you to render form fields with enhanced
customization.
```html
<!-- example_template.html -->
{% load paper_forms %}
<form method="post">
{% field form.name %}
{% field form.age %}
</form>
```
The rendered HTML will be similar to the standard Django form rendering, but with
the added flexibility provided by `paper-forms`. This sets the foundation for integrating
`paper-forms` seamlessly into your Django project.
## Composer Configuration
The real power of `paper-forms` lies in the ability to customize form rendering
using the `BaseComposer` class. Let's explore how you can leverage this class to tailor
the rendering of your forms.
One of the key features of `paper-forms` is the ability to customize form widgets.
In your Django form, you can define a `Composer` class that inherits from `BaseComposer`
to specify different widgets for specific fields.
```python
# forms.py
from django import forms
from paper_forms.composer import BaseComposer
class ExampleForm(forms.Form):
name = forms.CharField()
password = forms.CharField()
class Composer(BaseComposer):
widgets = {
"password": forms.PasswordInput,
}
```
In this example, the `Composer` class defines a custom widget for the "password" field.
This allows you to have fine-grained control over the rendering of individual form fields.
`paper-forms` also allows you to set labels and help text for form fields, either
globally or on a per-field basis.
```python
# forms.py
from django import forms
from paper_forms.composer import BaseComposer
class ExampleForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField()
class Composer(BaseComposer):
labels = {
"name": "Your Full Name",
"age": "Your Age",
}
help_texts = {
"name": "Enter your full name as it appears on official documents.",
"age": "Please provide your current age.",
}
```
Here, the `Composer` class provides labels and help text for the "name" and "age" fields,
offering clear instructions to users interacting with your forms.
Additionally, developers can enhance the customization of the form's appearance
by utilizing the `error_css_class` and `required_css_class` attributes
within the `Composer` class. These attributes allow you to define specific CSS classes
for handling errors and indicating required fields, respectively. Notably, any values
set for these attributes in the `Composer` class take precedence over those specified
at the form level.
### Specifying Custom Template Names
When using `paper-forms`, you have the flexibility to create custom templates for
individual form fields. This can be achieved by leveraging the `Composer` class
and specifying custom template names for each field. Let's go through an example
of how a custom form field template might look:
Assume you have a Django form with a field named "name," and you want to create
a custom template for rendering this specific field.
1. **Create the Custom Template**<br>
Create a new HTML file, let's call it `custom_field.html`, and place
it in your Django app's templates directory. Here's a simplified example of how
the template might look:
```html
<!-- custom_field.html -->
<div class="form-field {{ css_classes }}">
<label for="{{ widget.attrs.id }}">{{ label }}</label>
<!-- include default widget template -->
{% include widget.template_name %}
<!-- show field errors -->
{% if errors %}
<ul>
{% for error in errors %}
<li>{{ error }}</li>
{% endfor %}
</ul>
{% endif %}
<!-- show help text -->
{% if help_text %}
<small>{{ help_text }}</small>
{% endif %}
</div>
```
In this example, the template includes a custom structure for rendering
the form field, including a label, the actual form widget, error messages,
and help text.
2. **Update the Composer Class**<br>
Now, update the `Composer` class in your Django form to specify the custom
template name for the "name" field:
```python
from django import forms
from paper_forms.composer import BaseComposer
class ExampleForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField()
class Composer(BaseComposer):
template_names = {
"name": "path/to/custom_field.html",
}
```
Ensure that the path provided in template_names matches the location of your custom
template file.
3. **Render the Form in Your Template**<br>
In your Django template where you render the form, use the `{% field %}` template
tag for the "name" field:
```html
{% load paper_forms %}
<form method="post">
{% field form.name %}
{% field form.age %}
<button type="submit">Submit</button>
</form>
```
When the form is rendered, the "name" field will use your custom template,
while other fields will follow the default rendering.
By following these steps, you can create and apply custom templates for specific form
fields, providing a tailored look and feel for different parts of your Django forms.
### Customizing Form Field Rendering in Composer
The `paper-forms` library provides extensive flexibility through the `Composer` class,
allowing you to customize the rendering of form fields. In addition to specifying custom
templates, you can achieve advanced customization by overriding methods in the
`BaseComposer` class. Let's explore an example of how to override methods to replace
`labels` with `placeholders` across all form fields.
Suppose you want to make a global change to the rendering of form fields, replacing
labels with placeholders.
Step 1: Create a Custom Composer.
Create a custom `Composer` subclass with the desired customization for form
field rendering.
```python
# composers.py
from paper_forms.composer import BaseComposer
class CustomComposer(BaseComposer):
placeholders: dict = None
def get_label(self, name, widget):
# Override get_label method to return an empty string
# for all fields.
return ""
def build_widget_attrs(self, name, attrs, widget):
attrs = super().build_widget_attrs(name, attrs, widget)
placeholder = attrs.get("placeholder")
if placeholder is None and self.placeholders:
placeholder = self.placeholders[name]
if placeholder:
attrs["placeholder"] = placeholder
return attrs
```
Step 2: Use Custom Composer in a Django Form.
Apply the custom `CustomComposer` class to a Django form.
```python
# forms.py
from django import forms
from .composers import CustomComposer
class ExampleForm(forms.Form):
name = forms.CharField()
age = forms.IntegerField()
class Composer(CustomComposer):
placeholders = {
"name": "Enter your name",
"age": "Enter your age",
}
```
Step 3: Render the Form in Your Template.
Use the `{% field %}` template tag to render the form in your template.
```html
{% load paper_forms %}
<form method="post">
{% field form.name %}
{% field form.age %}
<button type="submit">Submit</button>
</form>
```
With this setup, the "name" and "age" fields will have placeholders instead of labels.
### Customizing Composer Class
In addition to the specific methods discussed earlier, the `BaseComposer` class
in the `paper-forms` library provides several other methods that developers can override
to further customize form field rendering. Below are some of the additional methods
available for customization:
`get_widget(self, name: str) -> Widget`
Retrieves a widget for a specific form field. By default, it looks up the widget
in the `widgets` dictionary. If `None` is returned, the default widget for the field
will be used.
`get_template_name(self, name: str, widget: Widget) -> str`
Determines the template name to be used for rendering a form field. It considers
hidden widgets, specific template names in the template_names dictionary, and
falls back to the default template name.
`get_default_template_name(self, name: str, widget: Widget) -> str`
This method plays a crucial role in simplifying the creation of Composer classes for
frameworks like Bootstrap. This method is designed to facilitate the customization
of form field templates without affecting the ability to specify template paths via
the `template_names` attribute in the `Composer` class.
When rendering a form field, the `get_default_template_name` method is called
to determine the default template name based on the provided field name and widget.
This method can be overridden in custom Composer classes to set a default template name,
allowing for a more streamlined implementation of framework-specific Composers.
```python
from django.forms.widgets import TextInput, NumberInput
from paper_forms.composer import BaseComposer
class FrameworkComposer(BaseComposer):
def get_default_template_name(self, name, widget) -> str:
if isinstance(widget, TextInput):
return f"bootstrap/text_field.html"
elif isinstance(widget, NumberInput):
return f"bootstrap/number_field.html"
# Fall back to the default behavior
return super().get_default_template_name(name, widget)
```
`get_label(self, name: str, widget: Widget) -> Optional[str]`
Retrieves the label for a form field. It looks up the label in the `labels` dictionary.
If `None` is returned, the default label for the field will be used.
`get_help_text(self, name: str, widget: Widget) -> Optional[str]`
Retrieves the help text for a form field. It looks up the help text in the `help_texts`
dictionary. If `None` is returned, the default help text for the field will be used.
`get_css_classes(self, name: str, widget: Widget) -> Optional[str]`
Retrieves the CSS classes for a form field. It looks up the CSS classes
in the `css_classes` dictionary.
`build_widget_attrs(self, name: str, attrs: Optional[dict], widget: Widget) -> dict`
Builds and customizes the attributes for a form field's widget. Developers can add,
remove, or modify attributes based on field names or other criteria.
`build_context(self, name: str, context: Optional[dict], widget: Widget) -> dict`
Builds the context to be passed to the form field template. Developers can add
or modify context variables based on field names or other conditions.
## Template Tags
`paper-forms` provides template tags to simplify the integration of the library into
your Django templates. The primary tag is `{% field %}`, which allows you to render
form fields with enhanced customization options.
The `{% field %}` tag is the key to leveraging the features provided by `paper-forms`.
It allows you to render form fields with various attributes and context variables.
```html
{% load paper_forms %}
<form method="post">
{% field form.name placeholder="Enter your name" %}
{% field form.age placeholder="Enter your age" _style="light" %}
</form>
```
In this example, the `{% field %}` tag is used to render the "name" and "age" fields
of the form. Attributes such as `placeholder` and `style` are passed as parameters
to customize the rendering.
The `{% field %}` tag supports adding variables to the form field template using
the "_" prefix in the template tag parameters. These variables become part
of the template context for the form field.
In the example above, the `placeholder` attribute is a widget attribute, while
the `_style` is a template context variable. Parameters with a leading underscore,
such as `_style`, are treated as template context variables.
## Configuration
`paper-forms` provides additional configuration options that you can set in your
Django project's settings.
You can specify the default `Composer` class to be used for any form that doesn't specify
a particular composer. This is set using the `PAPER_FORMS_DEFAULT_COMPOSER` setting.
```python
# settings.py
PAPER_FORMS_DEFAULT_COMPOSER = "myapp.composers.CustomComposer"
```
Here, `myapp.composers.CustomComposer` is the custom composer class you want to use
as the default.
The default form renderer can be set using the `PAPER_FORMS_DEFAULT_FORM_RENDERER` setting.
```python
# settings.py
PAPER_FORMS_DEFAULT_FORM_RENDERER = "django.forms.renderers.TemplatesSetting"
```
In this example, `django.forms.renderers.TemplatesSetting` is used as the default
form renderer.
## Common Issues and Workarounds
In the course of using `paper-forms`, you may encounter some common issues. This section
provides explanations and workarounds for these issues to help you navigate potential
challenges.
### Dashes in Attribute Names
If you are trying to specify an attribute with dashes in the `{% field %}` template tag,
like `data-src`, you might face limitations. This is due to the restrictive nature of
`@simple_tag`, which [does not allow dashes]((https://code.djangoproject.com/ticket/21077))
in kwargs names.
To overcome this limitation, use double underscores. All double underscores in
`{% field %}` arguments are replaced with single dashes. For example:
```html
{% field form.name data__original__name="Name" %}
```
This would render to something like
```html
<input ... data-original-name="Name" />
```
### `FORM_RENDERER` Setting with Third-Party Template Engines
If you are using `django-jinja` or any other third-party template engine as your default
template engine, and you want to use it for your form field templates, you might face
challenges. Django's form widgets are rendered using form renderers, and changing the
`FORM_RENDERER` setting can break the admin interface.
Follow these steps to work around this problem:
1. Make built-in widget templates searchable:
```python
# settings.py
from pathlib import Path
from django import forms
TEMPLATES = [
{
"NAME": "jinja2",
"BACKEND": "django_jinja.backend.Jinja2",
"DIRS": [
BASE_DIR / "templates",
Path(forms.__file__).parent / "jinja2"
],
# ...
}
]
```
2. Use `TemplateSetting` renderer for your forms or implement your own. You can achieve
this in several ways:
* Set the `PAPER_FORMS_DEFAULT_FORM_RENDERER` setting in `settings.py`:
```python
# settings.py
PAPER_FORMS_DEFAULT_FORM_RENDERER = "django.forms.renderers.TemplatesSetting"
```
* Specify the `default_renderer` attribute in your form:
```python
from django import forms
from django.forms.renderers import TemplatesSetting
class ExampleForm(forms.Form):
default_renderer = TemplatesSetting
# ...
```
* Set the `renderer` field in your `Composer` class:
```python
from django import forms
from paper_forms.composer import BaseComposer
class ExampleForm(forms.Form):
name = forms.CharField()
class Composer(BaseComposer):
renderer = "django.forms.renderers.TemplatesSetting"
```
Raw data
{
"_id": null,
"home_page": "https://github.com/dldevinc/paper-forms",
"name": "paper-forms",
"maintainer": "Mihail Mishakin",
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": "x896321475@gmail.com",
"keywords": null,
"author": "Mihail Mishakin",
"author_email": "x896321475@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/64/01/50a62e8ac86c3bb72cb1291a9ac97a455d7d2b61612ab5c16cf8108c62f3/paper_forms-0.5.3.tar.gz",
"platform": "OS Independent",
"description": "# paper-forms\n\nThis library provides tools to simplify and customize the form rendering process in Django. \nIt includes the `BaseComposer` class for centralized management of form settings and extends \nthe functionality of `BoundField` for convenient customization of form fields.\n\n[](https://pypi.org/project/paper-forms/)\n[](https://github.com/dldevinc/paper-forms)\n[](https://pypi.org/project/paper-forms/)\n\n### Compatibility\n\n- `python` >= 3.9\n- `django` >= 3.2\n\n### Features\n\n- [Jinja2](https://jinja.palletsprojects.com/) support.\n- [django-jinja](https://github.com/niwinz/django-jinja) support.\n\n## Table of Contents\n\n1. [Installation](#Installation)\n2. [Basic Usage](#Basic-Usage)\n3. [Composer Configuration](#Composer-Configuration)\n 1. [Specifying Custom Template Names](#Specifying-Custom-Template-Names)\n 2. [Customizing Form Field Rendering in Composer](#Customizing-Form-Field-Rendering-in-Composer)\n 3. [Customizing Composer Class](#Customizing-Composer-Class)\n4. [Template Tags](#Template-Tags)\n5. [Common Issues and Workarounds](#Common-Issues-and-Workarounds)\n\n## Installation\n\nTo get started with `paper-forms`, you need to install the library using `pip`. \nEnsure you have Python 3.9 or later installed in your environment.\n\n```shell\npip install paper-forms\n```\n\nNext, add \"paper_forms\" to the `INSTALLED_APPS` in your Django project's `settings.py`:\n\n```python\nINSTALLED_APPS = (\n # ...\n \"paper_forms\",\n)\n```\n\n## Basic Usage\n\nStart by creating a simple Django form. No mixins or third-party classes are required. \nJust define your form as you normally would using Django's `forms` module.\n\n```python\n# forms.py\nfrom django import forms\n\nclass ExampleForm(forms.Form):\n name = forms.CharField()\n age = forms.IntegerField()\n```\n\nNow, let's render the form in your template using the `{% field %}` template tag \nprovided by `paper-forms`. This tag allows you to render form fields with enhanced \ncustomization.\n\n```html\n<!-- example_template.html -->\n{% load paper_forms %}\n\n<form method=\"post\">\n {% field form.name %}\n {% field form.age %}\n</form>\n```\n\nThe rendered HTML will be similar to the standard Django form rendering, but with \nthe added flexibility provided by `paper-forms`. This sets the foundation for integrating \n`paper-forms` seamlessly into your Django project.\n\n## Composer Configuration\n\nThe real power of `paper-forms` lies in the ability to customize form rendering \nusing the `BaseComposer` class. Let's explore how you can leverage this class to tailor \nthe rendering of your forms.\n\nOne of the key features of `paper-forms` is the ability to customize form widgets. \nIn your Django form, you can define a `Composer` class that inherits from `BaseComposer` \nto specify different widgets for specific fields.\n\n```python\n# forms.py\nfrom django import forms\nfrom paper_forms.composer import BaseComposer\n\nclass ExampleForm(forms.Form):\n name = forms.CharField()\n password = forms.CharField()\n\n class Composer(BaseComposer):\n widgets = {\n \"password\": forms.PasswordInput,\n }\n```\n\nIn this example, the `Composer` class defines a custom widget for the \"password\" field. \nThis allows you to have fine-grained control over the rendering of individual form fields.\n\n`paper-forms` also allows you to set labels and help text for form fields, either \nglobally or on a per-field basis.\n\n```python\n# forms.py\nfrom django import forms\nfrom paper_forms.composer import BaseComposer\n\nclass ExampleForm(forms.Form):\n name = forms.CharField()\n age = forms.IntegerField()\n\n class Composer(BaseComposer):\n labels = {\n \"name\": \"Your Full Name\",\n \"age\": \"Your Age\",\n }\n help_texts = {\n \"name\": \"Enter your full name as it appears on official documents.\",\n \"age\": \"Please provide your current age.\",\n }\n```\n\nHere, the `Composer` class provides labels and help text for the \"name\" and \"age\" fields, \noffering clear instructions to users interacting with your forms.\n\nAdditionally, developers can enhance the customization of the form's appearance \nby utilizing the `error_css_class` and `required_css_class` attributes \nwithin the `Composer` class. These attributes allow you to define specific CSS classes \nfor handling errors and indicating required fields, respectively. Notably, any values \nset for these attributes in the `Composer` class take precedence over those specified \nat the form level.\n\n### Specifying Custom Template Names\n\nWhen using `paper-forms`, you have the flexibility to create custom templates for \nindividual form fields. This can be achieved by leveraging the `Composer` class \nand specifying custom template names for each field. Let's go through an example \nof how a custom form field template might look:\n\nAssume you have a Django form with a field named \"name,\" and you want to create \na custom template for rendering this specific field.\n\n1. **Create the Custom Template**<br>\n Create a new HTML file, let's call it `custom_field.html`, and place \n it in your Django app's templates directory. Here's a simplified example of how \n the template might look:\n ```html\n <!-- custom_field.html -->\n\n <div class=\"form-field {{ css_classes }}\">\n <label for=\"{{ widget.attrs.id }}\">{{ label }}</label>\n \n <!-- include default widget template -->\n {% include widget.template_name %}\n\n <!-- show field errors -->\n {% if errors %}\n <ul>\n {% for error in errors %}\n <li>{{ error }}</li>\n {% endfor %}\n </ul>\n {% endif %}\n\n <!-- show help text -->\n {% if help_text %}\n <small>{{ help_text }}</small>\n {% endif %}\n </div>\n ```\n In this example, the template includes a custom structure for rendering \n the form field, including a label, the actual form widget, error messages, \n and help text.\n2. **Update the Composer Class**<br>\n Now, update the `Composer` class in your Django form to specify the custom \n template name for the \"name\" field:\n ```python\n from django import forms\n from paper_forms.composer import BaseComposer\n\n class ExampleForm(forms.Form):\n name = forms.CharField()\n age = forms.IntegerField()\n\n class Composer(BaseComposer):\n template_names = {\n \"name\": \"path/to/custom_field.html\",\n }\n ```\n Ensure that the path provided in template_names matches the location of your custom \n template file.\n3. **Render the Form in Your Template**<br>\n In your Django template where you render the form, use the `{% field %}` template \n tag for the \"name\" field:\n ```html\n {% load paper_forms %}\n\n <form method=\"post\">\n {% field form.name %}\n {% field form.age %}\n <button type=\"submit\">Submit</button>\n </form>\n ```\n When the form is rendered, the \"name\" field will use your custom template, \n while other fields will follow the default rendering.\n\nBy following these steps, you can create and apply custom templates for specific form \nfields, providing a tailored look and feel for different parts of your Django forms.\n\n### Customizing Form Field Rendering in Composer\n\nThe `paper-forms` library provides extensive flexibility through the `Composer` class, \nallowing you to customize the rendering of form fields. In addition to specifying custom \ntemplates, you can achieve advanced customization by overriding methods in the \n`BaseComposer` class. Let's explore an example of how to override methods to replace \n`labels` with `placeholders` across all form fields.\n\nSuppose you want to make a global change to the rendering of form fields, replacing \nlabels with placeholders.\n\nStep 1: Create a Custom Composer.\n\nCreate a custom `Composer` subclass with the desired customization for form \nfield rendering.\n\n```python\n# composers.py\nfrom paper_forms.composer import BaseComposer\n\nclass CustomComposer(BaseComposer):\n placeholders: dict = None\n\n def get_label(self, name, widget):\n # Override get_label method to return an empty string \n # for all fields.\n return \"\"\n\n def build_widget_attrs(self, name, attrs, widget):\n attrs = super().build_widget_attrs(name, attrs, widget)\n placeholder = attrs.get(\"placeholder\")\n if placeholder is None and self.placeholders:\n placeholder = self.placeholders[name]\n if placeholder:\n attrs[\"placeholder\"] = placeholder\n return attrs\n```\n\nStep 2: Use Custom Composer in a Django Form.\n\nApply the custom `CustomComposer` class to a Django form.\n\n```python\n# forms.py\nfrom django import forms\nfrom .composers import CustomComposer\n\n\nclass ExampleForm(forms.Form):\n name = forms.CharField()\n age = forms.IntegerField()\n\n class Composer(CustomComposer):\n placeholders = {\n \"name\": \"Enter your name\",\n \"age\": \"Enter your age\",\n }\n```\n\nStep 3: Render the Form in Your Template.\n\nUse the `{% field %}` template tag to render the form in your template.\n\n```html\n{% load paper_forms %}\n\n<form method=\"post\">\n {% field form.name %}\n {% field form.age %}\n <button type=\"submit\">Submit</button>\n</form>\n```\n\nWith this setup, the \"name\" and \"age\" fields will have placeholders instead of labels.\n\n### Customizing Composer Class\n\nIn addition to the specific methods discussed earlier, the `BaseComposer` class \nin the `paper-forms` library provides several other methods that developers can override \nto further customize form field rendering. Below are some of the additional methods \navailable for customization:\n\n`get_widget(self, name: str) -> Widget`\n\nRetrieves a widget for a specific form field. By default, it looks up the widget \nin the `widgets` dictionary. If `None` is returned, the default widget for the field \nwill be used.\n\n`get_template_name(self, name: str, widget: Widget) -> str`\n\nDetermines the template name to be used for rendering a form field. It considers \nhidden widgets, specific template names in the template_names dictionary, and \nfalls back to the default template name.\n\n`get_default_template_name(self, name: str, widget: Widget) -> str`\n\nThis method plays a crucial role in simplifying the creation of Composer classes for \nframeworks like Bootstrap. This method is designed to facilitate the customization \nof form field templates without affecting the ability to specify template paths via \nthe `template_names` attribute in the `Composer` class.\n\nWhen rendering a form field, the `get_default_template_name` method is called \nto determine the default template name based on the provided field name and widget. \nThis method can be overridden in custom Composer classes to set a default template name, \nallowing for a more streamlined implementation of framework-specific Composers.\n\n```python\nfrom django.forms.widgets import TextInput, NumberInput\nfrom paper_forms.composer import BaseComposer\n\nclass FrameworkComposer(BaseComposer):\n def get_default_template_name(self, name, widget) -> str:\n if isinstance(widget, TextInput):\n return f\"bootstrap/text_field.html\"\n elif isinstance(widget, NumberInput):\n return f\"bootstrap/number_field.html\"\n\n # Fall back to the default behavior\n return super().get_default_template_name(name, widget)\n```\n\n`get_label(self, name: str, widget: Widget) -> Optional[str]`\n\nRetrieves the label for a form field. It looks up the label in the `labels` dictionary.\nIf `None` is returned, the default label for the field will be used.\n\n`get_help_text(self, name: str, widget: Widget) -> Optional[str]`\n\nRetrieves the help text for a form field. It looks up the help text in the `help_texts` \ndictionary. If `None` is returned, the default help text for the field will be used.\n\n`get_css_classes(self, name: str, widget: Widget) -> Optional[str]`\n\nRetrieves the CSS classes for a form field. It looks up the CSS classes \nin the `css_classes` dictionary.\n\n`build_widget_attrs(self, name: str, attrs: Optional[dict], widget: Widget) -> dict`\n\nBuilds and customizes the attributes for a form field's widget. Developers can add, \nremove, or modify attributes based on field names or other criteria.\n\n`build_context(self, name: str, context: Optional[dict], widget: Widget) -> dict`\n\nBuilds the context to be passed to the form field template. Developers can add \nor modify context variables based on field names or other conditions.\n\n## Template Tags\n\n`paper-forms` provides template tags to simplify the integration of the library into \nyour Django templates. The primary tag is `{% field %}`, which allows you to render \nform fields with enhanced customization options.\n\nThe `{% field %}` tag is the key to leveraging the features provided by `paper-forms`. \nIt allows you to render form fields with various attributes and context variables.\n\n```html\n{% load paper_forms %}\n\n<form method=\"post\">\n {% field form.name placeholder=\"Enter your name\" %}\n {% field form.age placeholder=\"Enter your age\" _style=\"light\" %}\n</form>\n```\n\nIn this example, the `{% field %}` tag is used to render the \"name\" and \"age\" fields \nof the form. Attributes such as `placeholder` and `style` are passed as parameters \nto customize the rendering.\n\nThe `{% field %}` tag supports adding variables to the form field template using \nthe \"_\" prefix in the template tag parameters. These variables become part \nof the template context for the form field.\n\nIn the example above, the `placeholder` attribute is a widget attribute, while \nthe `_style` is a template context variable. Parameters with a leading underscore, \nsuch as `_style`, are treated as template context variables.\n\n## Configuration\n\n`paper-forms` provides additional configuration options that you can set in your \nDjango project's settings.\n\nYou can specify the default `Composer` class to be used for any form that doesn't specify \na particular composer. This is set using the `PAPER_FORMS_DEFAULT_COMPOSER` setting.\n\n```python\n# settings.py\n\nPAPER_FORMS_DEFAULT_COMPOSER = \"myapp.composers.CustomComposer\"\n```\n\nHere, `myapp.composers.CustomComposer` is the custom composer class you want to use \nas the default.\n\nThe default form renderer can be set using the `PAPER_FORMS_DEFAULT_FORM_RENDERER` setting.\n\n```python\n# settings.py\n\nPAPER_FORMS_DEFAULT_FORM_RENDERER = \"django.forms.renderers.TemplatesSetting\"\n```\n\nIn this example, `django.forms.renderers.TemplatesSetting` is used as the default \nform renderer.\n\n## Common Issues and Workarounds\n\nIn the course of using `paper-forms`, you may encounter some common issues. This section \nprovides explanations and workarounds for these issues to help you navigate potential \nchallenges.\n\n### Dashes in Attribute Names\n\nIf you are trying to specify an attribute with dashes in the `{% field %}` template tag, \nlike `data-src`, you might face limitations. This is due to the restrictive nature of \n`@simple_tag`, which [does not allow dashes]((https://code.djangoproject.com/ticket/21077))\nin kwargs names.\n\nTo overcome this limitation, use double underscores. All double underscores in \n`{% field %}` arguments are replaced with single dashes. For example:\n\n```html\n{% field form.name data__original__name=\"Name\" %}\n```\n\nThis would render to something like\n\n```html\n<input ... data-original-name=\"Name\" />\n```\n\n### `FORM_RENDERER` Setting with Third-Party Template Engines\n\nIf you are using `django-jinja` or any other third-party template engine as your default\ntemplate engine, and you want to use it for your form field templates, you might face \nchallenges. Django's form widgets are rendered using form renderers, and changing the \n`FORM_RENDERER` setting can break the admin interface.\n\nFollow these steps to work around this problem:\n\n1. Make built-in widget templates searchable:\n ```python\n # settings.py\n\n from pathlib import Path\n from django import forms\n\n TEMPLATES = [\n {\n \"NAME\": \"jinja2\",\n \"BACKEND\": \"django_jinja.backend.Jinja2\",\n \"DIRS\": [\n BASE_DIR / \"templates\",\n Path(forms.__file__).parent / \"jinja2\"\n ],\n # ...\n }\n ]\n ```\n\n2. Use `TemplateSetting` renderer for your forms or implement your own. You can achieve \n this in several ways:\n * Set the `PAPER_FORMS_DEFAULT_FORM_RENDERER` setting in `settings.py`:\n ```python\n # settings.py\n\n PAPER_FORMS_DEFAULT_FORM_RENDERER = \"django.forms.renderers.TemplatesSetting\"\n ```\n * Specify the `default_renderer` attribute in your form:\n ```python\n from django import forms\n from django.forms.renderers import TemplatesSetting\n\n class ExampleForm(forms.Form):\n default_renderer = TemplatesSetting\n # ...\n ```\n * Set the `renderer` field in your `Composer` class:\n ```python\n from django import forms\n from paper_forms.composer import BaseComposer\n\n class ExampleForm(forms.Form):\n name = forms.CharField()\n\n class Composer(BaseComposer):\n renderer = \"django.forms.renderers.TemplatesSetting\"\n ```\n",
"bugtrack_url": null,
"license": "BSD license",
"summary": "A form templating app for Django",
"version": "0.5.3",
"project_urls": {
"Homepage": "https://github.com/dldevinc/paper-forms"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8e3521eef7151041f50fa9575d9096400de07684037f7980164a8a21366c503e",
"md5": "39fc73b28329149200954a2cb073fd97",
"sha256": "750c36d1b76dffbf238ace2864db7393e1dbc0f550858a1d4509b9502e80e0c5"
},
"downloads": -1,
"filename": "paper_forms-0.5.3-py2.py3-none-any.whl",
"has_sig": false,
"md5_digest": "39fc73b28329149200954a2cb073fd97",
"packagetype": "bdist_wheel",
"python_version": "py2.py3",
"requires_python": ">=3.9",
"size": 12248,
"upload_time": "2024-04-15T08:16:35",
"upload_time_iso_8601": "2024-04-15T08:16:35.556095Z",
"url": "https://files.pythonhosted.org/packages/8e/35/21eef7151041f50fa9575d9096400de07684037f7980164a8a21366c503e/paper_forms-0.5.3-py2.py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "640150a62e8ac86c3bb72cb1291a9ac97a455d7d2b61612ab5c16cf8108c62f3",
"md5": "e69edd2aade5db0bbd27fc4241cb024b",
"sha256": "8dada0d179feeac023e49621293426b4ece54f6f5192f38a4bceab3c9dcc76bc"
},
"downloads": -1,
"filename": "paper_forms-0.5.3.tar.gz",
"has_sig": false,
"md5_digest": "e69edd2aade5db0bbd27fc4241cb024b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 17990,
"upload_time": "2024-04-15T08:16:37",
"upload_time_iso_8601": "2024-04-15T08:16:37.331484Z",
"url": "https://files.pythonhosted.org/packages/64/01/50a62e8ac86c3bb72cb1291a9ac97a455d7d2b61612ab5c16cf8108c62f3/paper_forms-0.5.3.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-04-15 08:16:37",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "dldevinc",
"github_project": "paper-forms",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"requirements": [
{
"name": "jinja2",
"specs": []
},
{
"name": "django-jinja",
"specs": []
},
{
"name": "jinja2-simple-tags",
"specs": []
},
{
"name": "pytest",
"specs": [
[
"==",
"7.4.2"
]
]
},
{
"name": "pytest-cov",
"specs": [
[
"==",
"4.1.0"
]
]
},
{
"name": "pytest-django",
"specs": [
[
"==",
"4.5.2"
]
]
},
{
"name": "pytest-xdist",
"specs": [
[
"==",
"3.3.1"
]
]
}
],
"tox": true,
"lcname": "paper-forms"
}