1
0
mirror of https://github.com/django/django.git synced 2024-12-22 17:16:24 +00:00

Fixed #32340 -- Improved usability for form fields with specific input patterns.

This commit is contained in:
Ayush khatri 2024-12-20 20:34:40 +05:30
parent f05edb2b43
commit 25a2631d64
5 changed files with 63 additions and 1 deletions

View File

@ -19,6 +19,7 @@ from django.conf import settings
from django.core import validators from django.core import validators
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms.boundfield import BoundField from django.forms.boundfield import BoundField
from django.forms.fields import Field as DjangoField
from django.forms.utils import from_current_timezone, to_current_timezone from django.forms.utils import from_current_timezone, to_current_timezone
from django.forms.widgets import ( from django.forms.widgets import (
FILE_INPUT_CONTRADICTION, FILE_INPUT_CONTRADICTION,
@ -29,6 +30,7 @@ from django.forms.widgets import (
EmailInput, EmailInput,
FileInput, FileInput,
HiddenInput, HiddenInput,
Input,
MultipleHiddenInput, MultipleHiddenInput,
NullBooleanSelect, NullBooleanSelect,
NumberInput, NumberInput,
@ -1408,3 +1410,14 @@ class JSONField(CharField):
return json.dumps(initial, sort_keys=True, cls=self.encoder) != json.dumps( return json.dumps(initial, sort_keys=True, cls=self.encoder) != json.dumps(
self.to_python(data), sort_keys=True, cls=self.encoder self.to_python(data), sort_keys=True, cls=self.encoder
) )
class CustomField(DjangoField):
def __init__(self, *, widget=None, placeholder=None, **kwargs):
self.placeholder = placeholder
widget = widget or Input()
if self.placeholder:
widget.attrs.setdefault("placeholder", self.placeholder)
super().__init__(widget=widget, **kwargs)

View File

@ -1 +1,3 @@
<input type="{{ widget.type }}" name="{{ widget.name }}"{% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}> <input type="{{ widget.type }}" name="{{ widget.name }}"{% if widget.value != None %} value="{{ widget.value|stringformat:'s' }}"{% endif %}{% include "django/forms/widgets/attrs.html" %}>
{% if widget.attrs.placeholder %}placeholder="{{ widget.attrs.placeholder }}" {% endif %}>

View File

@ -1226,3 +1226,25 @@ class SelectDateWidget(Widget):
("{}_{}".format(name, interval) in data) ("{}_{}".format(name, interval) in data)
for interval in ("year", "month", "day") for interval in ("year", "month", "day")
) )
class Input(Widget):
input_type = None # Subclass must define this
def __init__(self, attrs=None, placeholder=None):
self.placeholder = placeholder # Add placeholder attribute
super().__init__(attrs)
def get_context(self, name, value, attrs):
context = super().get_context(name, value, attrs)
if self.placeholder:
attrs = attrs or {}
attrs.setdefault("placeholder", self.placeholder)
context["widget"]["attrs"] = attrs
return context
def render(self, name, value, attrs=None, renderer=None):
attrs = attrs or {}
if self.placeholder:
attrs["placeholder"] = self.placeholder
return super().render(name, value, attrs, renderer)

View File

@ -1627,3 +1627,13 @@ only requirements are that it implement a ``clean()`` method and that its
You can also customize how a field will be accessed by overriding You can also customize how a field will be accessed by overriding
:meth:`~django.forms.Field.get_bound_field()`. :meth:`~django.forms.Field.get_bound_field()`.
DateField
---------
Use this field to input dates. The default expected format is ``YYYY-MM-DD``.
For example: ``2024-12-31``.
TimeField
---------
Use this field to input time. The default expected format is ``HH:MM``.
For example: ``14:30``.

View File

@ -1,5 +1,6 @@
from django.contrib.admin.tests import AdminSeleniumTestCase from django.contrib.admin.tests import AdminSeleniumTestCase
from django.test import override_settings from django.forms import CharField, Form, TextInput
from django.test import SimpleTestCase, override_settings
from django.urls import reverse from django.urls import reverse
from ..models import Article from ..models import Article
@ -22,3 +23,17 @@ class LiveWidgetTests(AdminSeleniumTestCase):
self.selenium.find_element(By.ID, "submit").click() self.selenium.find_element(By.ID, "submit").click()
article = Article.objects.get(pk=article.pk) article = Article.objects.get(pk=article.pk)
self.assertEqual(article.content, "\r\nTst\r\n") self.assertEqual(article.content, "\r\nTst\r\n")
class WidgetPlaceholderTests(SimpleTestCase):
def test_placeholder_in_input_widget(self):
widget = TextInput(attrs={"placeholder": "Enter text"})
output = widget.render("name", "")
self.assertIn('placeholder="Enter text"', output)
def test_placeholder_in_field(self):
class ExampleForm(Form):
name = CharField(widget=TextInput(attrs={"placeholder": "Your name"}))
form = ExampleForm()
self.assertIn('placeholder="Your name"', str(form["name"]))