Fix widget attrs being dropped from rendered inputs, and redesign the referee PDF
field.html's "input" branch rendered type/class/name/value/placeholder only, silently dropping every other widget attr -- so a NumberInput's step="any" (added to let the per-km rate take values like 0.083) never reached the page, and the browser fell back to whole-number-only validation. Pass widget attrs through the same way the "select" branch already does. Also gives the referee payment PDF a proper visual pass (accent header, an info card for the game details, a real fee/km table with a grand-total row) instead of the plain label/dotted-line layout, and lets the dashboard tile show assigned referees with a "referee form" download button per tile. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -24,6 +24,7 @@
|
||||
name="{{ field.html_name }}"
|
||||
value="{% if field.widget_type == "date" or field.widget_type == "datetime" %}{% if field.value|date:"c"|default:"" != "" %}{{ field.value|date:"c"|default:"" }}{% else %}{{ field.value|default:"" }}{% endif %}{% else %}{% if field.value == None %}{{ field.value|default:"" }}{% else %}{{ field.value }}{% endif %}{% endif %}"
|
||||
{% if show_placeholder %}placeholder="{{ field.label|capfirst }}"{% endif %}
|
||||
{% for attr, value in field.field.widget.attrs.items %}{% if attr != "type" %}{{ attr }}="{{ value }}" {% endif %}{% endfor %}
|
||||
/>
|
||||
|
||||
{% elif field_type == "checkbox" %}
|
||||
|
||||
@@ -11,6 +11,7 @@ from django.contrib.auth import get_user_model
|
||||
from django.contrib.messages.storage.base import Message
|
||||
from django.contrib.messages.storage.fallback import FallbackStorage
|
||||
from django.core.cache import cache
|
||||
from django.template.loader import render_to_string
|
||||
from django.test import RequestFactory, TestCase, override_settings
|
||||
from django.urls import reverse
|
||||
from django.utils import timezone
|
||||
@@ -50,7 +51,7 @@ from .services.statistics import (
|
||||
teams_without_a_manager,
|
||||
unrostered_members,
|
||||
)
|
||||
from .templatetags.ui import as_alert, daisy, excluded, field_icon
|
||||
from .templatetags.ui import as_alert, daisy, excluded, field_icon, form_field
|
||||
|
||||
User = get_user_model()
|
||||
Flag = get_waffle_flag_model()
|
||||
@@ -691,6 +692,20 @@ class FieldRenderingTests(TestCase):
|
||||
|
||||
self.assertIn("input-error", rendered)
|
||||
|
||||
def test_the_form_field_tag_carries_widget_attrs_onto_the_input(self):
|
||||
# Regression: the "input" branch of templatetags/field.html rendered type/
|
||||
# class/name/value/placeholder only, silently dropping every other widget
|
||||
# attr (step, min, ...) -- e.g. NumberInput(attrs={"step": "any"}) never
|
||||
# reached the page, so a decimal-only field like a per-km rate couldn't be
|
||||
# typed at all. See form_field in controlpanel/templatetags/ui.py.
|
||||
bound_field = self.field(forms.DecimalField(widget=forms.NumberInput(attrs={"step": "any", "min": "0"})), "rate")
|
||||
|
||||
html = render_to_string("templatetags/field.html", form_field(bound_field))
|
||||
|
||||
self.assertIn('step="any"', html)
|
||||
self.assertIn('min="0"', html)
|
||||
self.assertEqual(html.count('type="number"'), 1)
|
||||
|
||||
|
||||
class LoginFormRenderingTests(TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user