Skip to content

Commit

Permalink
Merge branch 'django-crispy-forms:main' into main
Browse files Browse the repository at this point in the history
  • Loading branch information
GitRon authored Feb 6, 2024
2 parents 0a41ab6 + 7142835 commit ed98af5
Show file tree
Hide file tree
Showing 13 changed files with 652 additions and 25 deletions.
43 changes: 43 additions & 0 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ on:
- main
pull_request:

permissions:
contents: read

jobs:
tests:
name: Python ${{ matrix.python-version }}
Expand Down Expand Up @@ -51,3 +54,43 @@ jobs:
flags: unittests
name: codecov-umbrella
fail_ci_if_error: false


deploy:
name: Deploy
needs: [tests]
runs-on: ubuntu-latest
if: github.ref=='refs/heads/main' && github.event_name!='pull_request'

permissions:
contents: write
id-token: write

steps:
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.10"

- name: Check release
id: check_release
run: |
python -m pip install autopub
python -m pip install https://github.com/j0057/github-release/archive/master.zip
autopub check
- name: Publish
if: ${{ steps.check_release.outputs.autopub_release=='true' }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
autopub prepare
autopub commit
autopub build
autopub githubrelease
- name: Upload package to PyPI
if: ${{ steps.check_release.outputs.autopub_release=='true' }}
uses: pypa/gh-action-pypi-publish@release/v1
25 changes: 17 additions & 8 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
# CHANGELOG for crispy-tailwind
CHANGELOG
=========

## Next Release (tbc)
1.0.0 - 2024-01-09
------------------

## 1.0 (2024-01-09)
* Added support for Django 5.0 (#142)
* Added support for Python 3.11 and 3.12 (#142)
* Added support for Python 3.10 (#116)
Expand All @@ -15,30 +16,37 @@
* Added docs about Tailwind CLI template discovery management command (#144)
* Fixed bug with select template and disabled property (#118)

## 0.5 (2021-04-21)
0.5.0 - 2021-04-21
------------------

* Added support for custom widgets (#92)
* Confirmed support for Django 3.2 (#91)
* Dropped support for Django 3.1 (#91)

See [Release Notes](https://github.com/django-crispy-forms/crispy-tailwind/milestone/5?closed=1)
for full change log.

## 0.4 (2021-03-22)
0.4.0 - 2021-03-22
------------------

* Fixed compatibility with django-crispy-forms 1.11.2 (#86)
* Fixed field names when using formsets (#84)

See [Release Notes](https://github.com/django-crispy-forms/crispy-tailwind/milestone/4?closed=1)
for full change log.

## 0.3 (2021-02-14)
0.3.0 - 2021-02-14
------------------

* Fixed non form errors (#77)
* Various documentation improvements
* Python 3.9 (#60) and Django 3.1 (#56) support

See [Release Notes](https://github.com/django-crispy-forms/crispy-tailwind/milestone/3?closed=1)
for full change log.

## 0.2 (2020-07-11)
0.2.0 - 2020-07-11
------------------

* Support for Formsets
* Prepended and Appended inputs
Expand All @@ -50,7 +58,8 @@ for full change log.
See [Release Notes](https://github.com/django-crispy-forms/crispy-tailwind/milestone/2?closed=1)
for full change log.

## 0.1 (2020-06-09)
0.1.0 - 2020-06-09
------------------

* First Release, please do come and test!
* Opinionated forms can be rendered with crispy filter
Expand Down
1 change: 1 addition & 0 deletions crispy_tailwind/templates/tailwind/layout/attrs.html
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% for name, value in widget.attrs.items %}{% if value is not False %} {{ name }}{% if value is not True %}="{{ value|stringformat:'s' }}"{% endif %}{% endif %}{% endfor %}
24 changes: 15 additions & 9 deletions crispy_tailwind/templates/tailwind/layout/select.html
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
{% load crispy_forms_filters %}
{% load tailwind_filters %}
{% load l10n %}

<div class="relative">
<select class="{% if field.errors %}border border-red-500 {% endif %}{% if field.field.disabled %}bg-gray-100{% else %}bg-white{% endif %} focus:outline-none border border-gray-300 rounded-lg py-2 px-4 block w-full appearance-none leading-normal text-gray-700"
name="{{ field.html_name }}" {{ field.field.widget.attrs|flatatt }}
{% if field.field.disabled %}disabled{% endif %}>
{% for value, label in field.field.choices %}
{% include "tailwind/layout/select_option.html" with value=value label=label %}
{% endfor %}
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
<select class="bg-white focus:outline-none border {% if field.errors %}border-red-500 {% else %}border-gray-300 {% endif %}rounded-lg py-2 px-4 block w-full appearance-none leading-normal text-gray-700" name="{{ field.html_name }}" {{ field|build_attrs }}>
{% for group, options, index in field|optgroups %}
{% if group %}<optgroup label="{{ group }}">{% endif %}
{% for option in options %}
{% include "tailwind/layout/select_option.html" %}
{% endfor %}
{% if group %}</optgroup>{% endif %}
{% endfor %}
</select>
{% if not field.field.widget.allow_multiple_selected %}
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2 text-gray-700">
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20"><path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"/></svg>
</div>
{% endif %}
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{% load crispy_forms_filters %}
{% load l10n %}

<option value="{{ value|stringformat:'s' }}" {{ field.field.widget.attrs|flatatt }}{% if field.value|stringformat:'s' == value|stringformat:'s' %} selected{% endif %}>{{ label }}</option>
<option value="{{ option.value|stringformat:'s' }}" {% include "tailwind/layout/attrs.html" with widget=option %} >{{ option.label }}</option>
25 changes: 25 additions & 0 deletions crispy_tailwind/templatetags/tailwind_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,3 +127,28 @@ def as_crispy_field(field, template_pack=TEMPLATE_PACK, label_class="", field_cl
@register.filter(name="flatatt")
def flatatt_filter(attrs):
return mark_safe(flatatt(attrs))


@register.filter
def build_attrs(field):
"""
Build HTML attributes for a form field, also checking for a
``widget.allow_multiple_selected`` attribute and adding ``multiple`` to the
attributes if it is set to ``True``.
"""
attrs = field.field.widget.attrs
attrs.setdefault("id", field.auto_id)

field_built_widget_attrs = field.build_widget_attrs(attrs)
attrs.update(field_built_widget_attrs)

# Some custom widgets (e.g. Select2) may add additional attributes to the
# widget attrs dict. We need to add those to the attrs dict as well calling
# the widget's build_attrs method.

built_widget_attrs = field.field.widget.build_attrs(attrs)
attrs.update(built_widget_attrs)

if hasattr(field.field.widget, "allow_multiple_selected"):
attrs["multiple"] = attrs.get("multiple", field.field.widget.allow_multiple_selected)
return mark_safe(flatatt(attrs))
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,12 @@ version = {attr = "crispy_tailwind.__version__"}
"Issues" = "https://github.com/django-crispy-forms/crispy-tailwind/issues"
"Changelog" = "https://github.com/django-crispy-forms/crispy-tailwind/releases"

[tool.autopub]
project-name = "Crispy-Tailwind"
git-username = "botpub"
git-email = "[email protected]"
append-github-contributor = true

[tool.black]
line-length = 119
target-version = ['py38']
Expand Down
25 changes: 25 additions & 0 deletions tests/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,31 @@ class SampleForm(forms.Form):
widget=forms.Select(),
choices=(("accepted", "Accepted"), ("not_accepted", "Not accepted")),
)
select_multiple = forms.MultipleChoiceField(choices=[("1", "one"), ("2", "two"), ("3", "three")])
select_required = forms.ChoiceField(
choices=[("", "Select and option"), ("1", "one"), ("2", "two"), ("3", "three")],
initial="2",
)
grouped_select = forms.TypedChoiceField(
choices=[
(
"Group 1",
[
("1", "one"),
("2", "two"),
],
),
(
"Group 2",
[
("3", "three"),
("4", "four"),
],
),
],
coerce=str,
widget=forms.Select(attrs={"class": "custom-class"}),
)

def clean(self):
super().clean()
Expand Down
97 changes: 96 additions & 1 deletion tests/results/filter/crispy_filter.html
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@
<div class="mb-3">
<div class="relative">
<select class="bg-white focus:outline-none border border-gray-300 rounded-lg py-2 px-4 block w-full
appearance-none leading-normal text-gray-700" name="tos_accepted">
appearance-none leading-normal text-gray-700" name="tos_accepted" id="id_tos_accepted">
<option value="accepted">Accepted</option>
<option value="not_accepted">Not accepted</option>
</select>
Expand All @@ -75,3 +75,98 @@
</div>
</div>
</div>

<div class="mb-3" id="div_id_select_multiple">
<label class="block font-bold mb-2 text-gray-700 text-sm" for="id_select_multiple">
Select multiple<span class="asteriskField">
*
</span>
</label>
<div class="mb-3">
<div class="relative">
<select
class="appearance-none bg-white block border border-gray-300 focus:outline-none leading-normal px-4 py-2 rounded-lg text-gray-700 w-full"
id="id_select_multiple" multiple name="select_multiple" required>
<option value="1">
one
</option>
<option value="2">
two
</option>
<option value="3">
three
</option>
</select>
</div>
</div>
</div>

<div class="mb-3" id="div_id_select_required">
<label class="block font-bold mb-2 text-gray-700 text-sm" for="id_select_required">
Select required<span class="asteriskField">
*
</span>
</label>
<div class="mb-3">
<div class="relative">
<select
class="appearance-none bg-white block border border-gray-300 focus:outline-none leading-normal px-4 py-2 rounded-lg text-gray-700 w-full"
id="id_select_required" name="select_required" required>
<option value="">
Select and option
</option>
<option value="1">
one
</option>
<option selected value="2">
two
</option>
<option value="3">
three
</option>
</select>
<div class="absolute flex inset-y-0 items-center pointer-events-none px-2 right-0 text-gray-700">
<svg class="fill-current h-4 w-4" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z">
</svg>
</div>
</div>
</div>
</div>

<div class="mb-3" id="div_id_grouped_select">
<label class="block font-bold mb-2 text-gray-700 text-sm" for="id_grouped_select">
Grouped select<span class="asteriskField">
*
</span>
</label>
<div class="mb-3">
<div class="relative">
<select
class="appearance-none bg-white block border border-gray-300 focus:outline-none leading-normal px-4 py-2 rounded-lg text-gray-700 w-full"
class="custom-class" id="id_grouped_select" name="grouped_select">
<optgroup label="Group 1">
<option value="1">
one
</option>
<option value="2">
two
</option>
</optgroup>
<optgroup label="Group 2">
<option value="3">
three
</option>
<option value="4">
four
</option>
</optgroup>
</select>
<div class="absolute flex inset-y-0 items-center pointer-events-none px-2 right-0 text-gray-700">
<svg class="fill-current h-4 w-4" viewbox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z">
</svg>
</div>
</div>
</div>
</div>
Loading

0 comments on commit ed98af5

Please sign in to comment.