summaryrefslogtreecommitdiff
path: root/docs/ref/forms
diff options
context:
space:
mode:
authordjango-bot <ops@djangoproject.com>2023-02-28 20:53:28 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2023-03-01 13:03:56 +0100
commit14459f80ee3a9e005989db37c26fd13bb6d2fab2 (patch)
treeeb62429ed696ed3a5389f3a676aecfc6d15a99cc /docs/ref/forms
parent6015bab80e28aef2669f6fac53423aa65f70cb08 (diff)
Fixed #34140 -- Reformatted code blocks in docs with blacken-docs.
Diffstat (limited to 'docs/ref/forms')
-rw-r--r--docs/ref/forms/api.txt219
-rw-r--r--docs/ref/forms/fields.txt102
-rw-r--r--docs/ref/forms/renderers.txt3
-rw-r--r--docs/ref/forms/validation.txt66
-rw-r--r--docs/ref/forms/widgets.txt71
5 files changed, 270 insertions, 191 deletions
diff --git a/docs/ref/forms/api.txt b/docs/ref/forms/api.txt
index f648ee7ec4..12754dbae5 100644
--- a/docs/ref/forms/api.txt
+++ b/docs/ref/forms/api.txt
@@ -36,10 +36,12 @@ your :class:`Form` class constructor:
.. code-block:: pycon
- >>> data = {'subject': 'hello',
- ... 'message': 'Hi there',
- ... 'sender': 'foo@example.com',
- ... 'cc_myself': True}
+ >>> data = {
+ ... "subject": "hello",
+ ... "message": "Hi there",
+ ... "sender": "foo@example.com",
+ ... "cc_myself": True,
+ ... }
>>> f = ContactForm(data)
In this dictionary, the keys are the field names, which correspond to the
@@ -58,7 +60,7 @@ check the value of the form's :attr:`~Form.is_bound` attribute:
>>> f = ContactForm()
>>> f.is_bound
False
- >>> f = ContactForm({'subject': 'hello'})
+ >>> f = ContactForm({"subject": "hello"})
>>> f.is_bound
True
@@ -93,10 +95,12 @@ and return a boolean designating whether the data was valid:
.. code-block:: pycon
- >>> data = {'subject': 'hello',
- ... 'message': 'Hi there',
- ... 'sender': 'foo@example.com',
- ... 'cc_myself': True}
+ >>> data = {
+ ... "subject": "hello",
+ ... "message": "Hi there",
+ ... "sender": "foo@example.com",
+ ... "cc_myself": True,
+ ... }
>>> f = ContactForm(data)
>>> f.is_valid()
True
@@ -107,10 +111,12 @@ email address:
.. code-block:: pycon
- >>> data = {'subject': '',
- ... 'message': 'Hi there',
- ... 'sender': 'invalid email address',
- ... 'cc_myself': True}
+ >>> data = {
+ ... "subject": "",
+ ... "message": "Hi there",
+ ... "sender": "invalid email address",
+ ... "cc_myself": True,
+ ... }
>>> f = ContactForm(data)
>>> f.is_valid()
False
@@ -256,7 +262,7 @@ it's not necessary to include every field in your form. For example:
.. code-block:: pycon
- >>> f = ContactForm(initial={'subject': 'Hi there!'})
+ >>> f = ContactForm(initial={"subject": "Hi there!"})
These values are only displayed for unbound forms, and they're not used as
fallback values if a particular value isn't provided.
@@ -271,10 +277,11 @@ precedence:
>>> from django import forms
>>> class CommentForm(forms.Form):
- ... name = forms.CharField(initial='class')
+ ... name = forms.CharField(initial="class")
... url = forms.URLField()
... comment = forms.CharField()
- >>> f = CommentForm(initial={'name': 'instance'}, auto_id=False)
+ ...
+ >>> f = CommentForm(initial={"name": "instance"}, auto_id=False)
>>> print(f)
<div>Name:<input type="text" name="name" value="instance" required></div>
<div>Url:<input type="url" name="url" required></div>
@@ -298,15 +305,16 @@ dealing with callables whose return values can change (e.g. ``datetime.now`` or
>>> import uuid
>>> class UUIDCommentForm(CommentForm):
... identifier = forms.UUIDField(initial=uuid.uuid4)
+ ...
>>> f = UUIDCommentForm()
- >>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
+ >>> f.get_initial_for_field(f.fields["identifier"], "identifier")
UUID('972ca9e4-7bfe-4f5b-af7d-07b3aa306334')
- >>> f.get_initial_for_field(f.fields['identifier'], 'identifier')
+ >>> f.get_initial_for_field(f.fields["identifier"], "identifier")
UUID('1b411fab-844e-4dec-bd4f-e9b0495f04d0')
>>> # Using BoundField.initial, for comparison
- >>> f['identifier'].initial
+ >>> f["identifier"].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
- >>> f['identifier'].initial
+ >>> f["identifier"].initial
UUID('28a09c59-5f00-4ed9-9179-a3b074fa9c30')
Checking which form data has changed
@@ -358,12 +366,13 @@ attribute:
.. code-block:: pycon
- >>> for row in f.fields.values(): print(row)
+ >>> for row in f.fields.values():
+ ... print(row)
...
<django.forms.fields.CharField object at 0x7ffaac632510>
<django.forms.fields.URLField object at 0x7ffaac632f90>
<django.forms.fields.CharField object at 0x7ffaac3aa050>
- >>> f.fields['name']
+ >>> f.fields["name"]
<django.forms.fields.CharField object at 0x7ffaac6324d0>
You can alter the field and :class:`.BoundField` of :class:`Form` instance to
@@ -409,10 +418,12 @@ it, you can access the clean data via its ``cleaned_data`` attribute:
.. code-block:: pycon
- >>> data = {'subject': 'hello',
- ... 'message': 'Hi there',
- ... 'sender': 'foo@example.com',
- ... 'cc_myself': True}
+ >>> data = {
+ ... "subject": "hello",
+ ... "message": "Hi there",
+ ... "sender": "foo@example.com",
+ ... "cc_myself": True,
+ ... }
>>> f = ContactForm(data)
>>> f.is_valid()
True
@@ -428,10 +439,12 @@ only the valid fields:
.. code-block:: pycon
- >>> data = {'subject': '',
- ... 'message': 'Hi there',
- ... 'sender': 'invalid email address',
- ... 'cc_myself': True}
+ >>> data = {
+ ... "subject": "",
+ ... "message": "Hi there",
+ ... "sender": "invalid email address",
+ ... "cc_myself": True,
+ ... }
>>> f = ContactForm(data)
>>> f.is_valid()
False
@@ -445,17 +458,19 @@ but ``cleaned_data`` contains only the form's fields:
.. code-block:: pycon
- >>> data = {'subject': 'hello',
- ... 'message': 'Hi there',
- ... 'sender': 'foo@example.com',
- ... 'cc_myself': True,
- ... 'extra_field_1': 'foo',
- ... 'extra_field_2': 'bar',
- ... 'extra_field_3': 'baz'}
+ >>> data = {
+ ... "subject": "hello",
+ ... "message": "Hi there",
+ ... "sender": "foo@example.com",
+ ... "cc_myself": True,
+ ... "extra_field_1": "foo",
+ ... "extra_field_2": "bar",
+ ... "extra_field_3": "baz",
+ ... }
>>> f = ContactForm(data)
>>> f.is_valid()
True
- >>> f.cleaned_data # Doesn't contain extra_field_1, etc.
+ >>> f.cleaned_data # Doesn't contain extra_field_1, etc.
{'cc_myself': True, 'message': 'Hi there', 'sender': 'foo@example.com', 'subject': 'hello'}
When the ``Form`` is valid, ``cleaned_data`` will include a key and value for
@@ -470,7 +485,8 @@ fields. In this example, the data dictionary doesn't include a value for the
... first_name = forms.CharField()
... last_name = forms.CharField()
... nick_name = forms.CharField(required=False)
- >>> data = {'first_name': 'John', 'last_name': 'Lennon'}
+ ...
+ >>> data = {"first_name": "John", "last_name": "Lennon"}
>>> f = OptionalPersonForm(data)
>>> f.is_valid()
True
@@ -513,10 +529,12 @@ include ``checked`` if appropriate:
.. code-block:: pycon
- >>> data = {'subject': 'hello',
- ... 'message': 'Hi there',
- ... 'sender': 'foo@example.com',
- ... 'cc_myself': True}
+ >>> data = {
+ ... "subject": "hello",
+ ... "message": "Hi there",
+ ... "sender": "foo@example.com",
+ ... "cc_myself": True,
+ ... }
>>> f = ContactForm(data)
>>> print(f)
<div><label for="id_subject">Subject:</label><input type="text" name="subject" value="hello" maxlength="100" required id="id_subject"></div>
@@ -764,9 +782,10 @@ attributes::
from django import forms
+
class ContactForm(forms.Form):
- error_css_class = 'error'
- required_css_class = 'required'
+ error_css_class = "error"
+ required_css_class = "required"
# ... and the rest of your fields here
@@ -781,13 +800,13 @@ classes, as needed. The HTML will look something like:
<div class="required"><label for="id_message" class="required">Message:</label> ...
<div class="required"><label for="id_sender" class="required">Sender:</label> ...
<div><label for="id_cc_myself">Cc myself:</label> ...
- >>> f['subject'].label_tag()
+ >>> f["subject"].label_tag()
<label class="required" for="id_subject">Subject:</label>
- >>> f['subject'].legend_tag()
+ >>> f["subject"].legend_tag()
<legend class="required" for="id_subject">Subject:</legend>
- >>> f['subject'].label_tag(attrs={'class': 'foo'})
+ >>> f["subject"].label_tag(attrs={"class": "foo"})
<label for="id_subject" class="foo required">Subject:</label>
- >>> f['subject'].legend_tag(attrs={'class': 'foo'})
+ >>> f["subject"].legend_tag(attrs={"class": "foo"})
<legend for="id_subject" class="foo required">Subject:</legend>
.. _ref-forms-api-configuring-label:
@@ -847,7 +866,7 @@ attributes based on the format string. For example, for a format string
.. code-block:: pycon
- >>> f = ContactForm(auto_id='id_for_%s')
+ >>> f = ContactForm(auto_id="id_for_%s")
>>> print(f)
<div><label for="id_for_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message:</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
@@ -869,13 +888,13 @@ It's possible to customize that character, or omit it entirely, using the
.. code-block:: pycon
- >>> f = ContactForm(auto_id='id_for_%s', label_suffix='')
+ >>> f = ContactForm(auto_id="id_for_%s", label_suffix="")
>>> print(f)
<div><label for="id_for_subject">Subject</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
<div><label for="id_for_sender">Sender</label><input type="email" name="sender" required id="id_for_sender"></div>
<div><label for="id_for_cc_myself">Cc myself</label><input type="checkbox" name="cc_myself" id="id_for_cc_myself"></div>
- >>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
+ >>> f = ContactForm(auto_id="id_for_%s", label_suffix=" ->")
>>> print(f)
<div><label for="id_for_subject">Subject:</label><input type="text" name="subject" maxlength="100" required id="id_for_subject"></div>
<div><label for="id_for_message">Message -&gt;</label><textarea name="message" cols="40" rows="10" required id="id_for_message"></textarea></div>
@@ -916,6 +935,7 @@ You can set this as a class attribute when declaring your form or use the
from django import forms
+
class MyForm(forms.Form):
default_renderer = MyRenderer()
@@ -964,10 +984,12 @@ method you're using:
.. code-block:: pycon
- >>> data = {'subject': '',
- ... 'message': 'Hi there',
- ... 'sender': 'invalid email address',
- ... 'cc_myself': True}
+ >>> data = {
+ ... "subject": "",
+ ... "message": "Hi there",
+ ... "sender": "invalid email address",
+ ... "cc_myself": True,
+ ... }
>>> f = ContactForm(data, auto_id=False)
>>> print(f)
<div>Subject:<ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" required></div>
@@ -1072,7 +1094,7 @@ using the field's name as the key:
.. code-block:: pycon
>>> form = ContactForm()
- >>> print(form['subject'])
+ >>> print(form["subject"])
<input id="id_subject" type="text" name="subject" maxlength="100" required>
To retrieve all ``BoundField`` objects, iterate the form:
@@ -1080,7 +1102,9 @@ To retrieve all ``BoundField`` objects, iterate the form:
.. code-block:: pycon
>>> form = ContactForm()
- >>> for boundfield in form: print(boundfield)
+ >>> for boundfield in form:
+ ... print(boundfield)
+ ...
<input id="id_subject" type="text" name="subject" maxlength="100" required>
<input type="text" name="message" id="id_message" required>
<input type="email" name="sender" id="id_sender" required>
@@ -1091,10 +1115,10 @@ The field-specific output honors the form object's ``auto_id`` setting:
.. code-block:: pycon
>>> f = ContactForm(auto_id=False)
- >>> print(f['message'])
+ >>> print(f["message"])
<input type="text" name="message" required>
- >>> f = ContactForm(auto_id='id_%s')
- >>> print(f['message'])
+ >>> f = ContactForm(auto_id="id_%s")
+ >>> print(f["message"])
<input type="text" name="message" id="id_message" required>
Attributes of ``BoundField``
@@ -1114,10 +1138,10 @@ Attributes of ``BoundField``
.. code-block:: pycon
>>> unbound_form = ContactForm()
- >>> print(unbound_form['subject'].data)
+ >>> print(unbound_form["subject"].data)
None
- >>> bound_form = ContactForm(data={'subject': 'My Subject'})
- >>> print(bound_form['subject'].data)
+ >>> bound_form = ContactForm(data={"subject": "My Subject"})
+ >>> print(bound_form["subject"].data)
My Subject
.. attribute:: BoundField.errors
@@ -1127,19 +1151,19 @@ Attributes of ``BoundField``
.. code-block:: pycon
- >>> data = {'subject': 'hi', 'message': '', 'sender': '', 'cc_myself': ''}
+ >>> data = {"subject": "hi", "message": "", "sender": "", "cc_myself": ""}
>>> f = ContactForm(data, auto_id=False)
- >>> print(f['message'])
+ >>> print(f["message"])
<input type="text" name="message" required>
- >>> f['message'].errors
+ >>> f["message"].errors
['This field is required.']
- >>> print(f['message'].errors)
+ >>> print(f["message"].errors)
<ul class="errorlist"><li>This field is required.</li></ul>
- >>> f['subject'].errors
+ >>> f["subject"].errors
[]
- >>> print(f['subject'].errors)
+ >>> print(f["subject"].errors)
- >>> str(f['subject'].errors)
+ >>> str(f["subject"].errors)
''
.. attribute:: BoundField.field
@@ -1177,7 +1201,7 @@ Attributes of ``BoundField``
:attr:`~django.forms.Widget.attrs` on the field's widget. For example,
declaring a field like this::
- my_field = forms.CharField(widget=forms.TextInput(attrs={'id': 'myFIELD'}))
+ my_field = forms.CharField(widget=forms.TextInput(attrs={"id": "myFIELD"}))
and using the template above, would render something like:
@@ -1201,10 +1225,11 @@ Attributes of ``BoundField``
>>> from datetime import datetime
>>> class DatedCommentForm(CommentForm):
... created = forms.DateTimeField(initial=datetime.now)
+ ...
>>> f = DatedCommentForm()
- >>> f['created'].initial
+ >>> f["created"].initial
datetime.datetime(2021, 7, 27, 9, 5, 54)
- >>> f['created'].initial
+ >>> f["created"].initial
datetime.datetime(2021, 7, 27, 9, 5, 54)
Using :attr:`BoundField.initial` is recommended over
@@ -1227,9 +1252,9 @@ Attributes of ``BoundField``
.. code-block:: pycon
>>> f = ContactForm()
- >>> print(f['subject'].name)
+ >>> print(f["subject"].name)
subject
- >>> print(f['message'].name)
+ >>> print(f["message"].name)
message
.. attribute:: BoundField.use_fieldset
@@ -1282,8 +1307,8 @@ Methods of ``BoundField``
.. code-block:: pycon
- >>> f = ContactForm(data={'message': ''})
- >>> f['message'].css_classes()
+ >>> f = ContactForm(data={"message": ""})
+ >>> f["message"].css_classes()
'required'
If you want to provide some additional classes in addition to the
@@ -1292,8 +1317,8 @@ Methods of ``BoundField``
.. code-block:: pycon
- >>> f = ContactForm(data={'message': ''})
- >>> f['message'].css_classes('foo bar')
+ >>> f = ContactForm(data={"message": ""})
+ >>> f["message"].css_classes("foo bar")
'foo bar required'
.. method:: BoundField.label_tag(contents=None, attrs=None, label_suffix=None, tag=None)
@@ -1327,8 +1352,8 @@ Methods of ``BoundField``
.. code-block:: pycon
- >>> f = ContactForm(data={'message': ''})
- >>> print(f['message'].label_tag())
+ >>> f = ContactForm(data={"message": ""})
+ >>> print(f["message"].label_tag())
<label for="id_message">Message:</label>
If you'd like to customize the rendering this can be achieved by overriding
@@ -1350,12 +1375,12 @@ Methods of ``BoundField``
.. code-block:: pycon
- >>> initial = {'subject': 'welcome'}
+ >>> initial = {"subject": "welcome"}
>>> unbound_form = ContactForm(initial=initial)
- >>> bound_form = ContactForm(data={'subject': 'hi'}, initial=initial)
- >>> print(unbound_form['subject'].value())
+ >>> bound_form = ContactForm(data={"subject": "hi"}, initial=initial)
+ >>> print(unbound_form["subject"].value())
welcome
- >>> print(bound_form['subject'].value())
+ >>> print(bound_form["subject"].value())
hi
Customizing ``BoundField``
@@ -1391,6 +1416,7 @@ be implemented as follows::
else:
return None
+
class GPSCoordinatesField(Field):
def get_bound_field(self, form, field_name):
return GPSCoordinatesBoundField(form, self, field_name)
@@ -1425,11 +1451,13 @@ need to bind the file data containing the mugshot image:
# Bound form with an image field
>>> from django.core.files.uploadedfile import SimpleUploadedFile
- >>> data = {'subject': 'hello',
- ... 'message': 'Hi there',
- ... 'sender': 'foo@example.com',
- ... 'cc_myself': True}
- >>> file_data = {'mugshot': SimpleUploadedFile('face.jpg', b"file data")}
+ >>> data = {
+ ... "subject": "hello",
+ ... "message": "Hi there",
+ ... "sender": "foo@example.com",
+ ... "cc_myself": True,
+ ... }
+ >>> file_data = {"mugshot": SimpleUploadedFile("face.jpg", b"file data")}
>>> f = ContactFormWithMugshot(data, file_data)
In practice, you will usually specify ``request.FILES`` as the source
@@ -1494,6 +1522,7 @@ fields are ordered first:
>>> class ContactFormWithPriority(ContactForm):
... priority = forms.CharField()
+ ...
>>> f = ContactFormWithPriority(auto_id=False)
>>> print(f)
<div>Subject:<input type="text" name="subject" maxlength="100" required></div>
@@ -1513,10 +1542,13 @@ classes:
>>> class PersonForm(forms.Form):
... first_name = forms.CharField()
... last_name = forms.CharField()
+ ...
>>> class InstrumentForm(forms.Form):
... instrument = forms.CharField()
+ ...
>>> class BeatleForm(InstrumentForm, PersonForm):
... haircut_type = forms.CharField()
+ ...
>>> b = BeatleForm(auto_id=False)
>>> print(b)
<div>First name:<input type="text" name="first_name" required></div>
@@ -1534,9 +1566,11 @@ by setting the name of the field to ``None`` on the subclass. For example:
>>> class ParentForm(forms.Form):
... name = forms.CharField()
... age = forms.IntegerField()
+ ...
>>> class ChildForm(ParentForm):
... name = None
+ ...
>>> list(ChildForm().fields)
['age']
@@ -1568,4 +1602,5 @@ The prefix can also be specified on the form class:
>>> class PersonForm(forms.Form):
... ...
- ... prefix = 'person'
+ ... prefix = "person"
+ ...
diff --git a/docs/ref/forms/fields.txt b/docs/ref/forms/fields.txt
index 727f494da2..317a955a15 100644
--- a/docs/ref/forms/fields.txt
+++ b/docs/ref/forms/fields.txt
@@ -26,9 +26,9 @@ value:
>>> from django import forms
>>> f = forms.EmailField()
- >>> f.clean('foo@example.com')
+ >>> f.clean("foo@example.com")
'foo@example.com'
- >>> f.clean('invalid email address')
+ >>> f.clean("invalid email address")
Traceback (most recent call last):
...
ValidationError: ['Enter a valid email address.']
@@ -55,9 +55,9 @@ an empty value -- either ``None`` or the empty string (``""``) -- then
>>> from django import forms
>>> f = forms.CharField()
- >>> f.clean('foo')
+ >>> f.clean("foo")
'foo'
- >>> f.clean('')
+ >>> f.clean("")
Traceback (most recent call last):
...
ValidationError: ['This field is required.']
@@ -65,7 +65,7 @@ an empty value -- either ``None`` or the empty string (``""``) -- then
Traceback (most recent call last):
...
ValidationError: ['This field is required.']
- >>> f.clean(' ')
+ >>> f.clean(" ")
' '
>>> f.clean(0)
'0'
@@ -80,9 +80,9 @@ To specify that a field is *not* required, pass ``required=False`` to the
.. code-block:: pycon
>>> f = forms.CharField(required=False)
- >>> f.clean('foo')
+ >>> f.clean("foo")
'foo'
- >>> f.clean('')
+ >>> f.clean("")
''
>>> f.clean(None)
''
@@ -124,9 +124,10 @@ We've specified ``auto_id=False`` to simplify the output:
>>> from django import forms
>>> class CommentForm(forms.Form):
- ... name = forms.CharField(label='Your name')
- ... url = forms.URLField(label='Your website', required=False)
+ ... name = forms.CharField(label="Your name")
+ ... url = forms.URLField(label="Your website", required=False)
... comment = forms.CharField()
+ ...
>>> f = CommentForm(auto_id=False)
>>> print(f)
<div>Your name:<input type="text" name="name" required></div>
@@ -146,8 +147,9 @@ The ``label_suffix`` argument lets you override the form's
>>> class ContactForm(forms.Form):
... age = forms.IntegerField()
... nationality = forms.CharField()
- ... captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')
- >>> f = ContactForm(label_suffix='?')
+ ... captcha_answer = forms.IntegerField(label="2 + 2", label_suffix=" =")
+ ...
+ >>> f = ContactForm(label_suffix="?")
>>> print(f)
<div><label for="id_age">Age?</label><input type="number" name="age" required id="id_age"></div>
<div><label for="id_nationality">Nationality?</label><input type="text" name="nationality" required id="id_nationality"></div>
@@ -170,9 +172,10 @@ field is initialized to a particular value. For example:
>>> from django import forms
>>> class CommentForm(forms.Form):
- ... name = forms.CharField(initial='Your name')
- ... url = forms.URLField(initial='http://')
+ ... name = forms.CharField(initial="Your name")
+ ... url = forms.URLField(initial="http://")
... comment = forms.CharField()
+ ...
>>> f = CommentForm(auto_id=False)
>>> print(f)
<div>Name:<input type="text" name="name" value="Your name" required></div>
@@ -189,7 +192,8 @@ and the HTML output will include any validation errors:
... name = forms.CharField()
... url = forms.URLField()
... comment = forms.CharField()
- >>> default_data = {'name': 'Your name', 'url': 'http://'}
+ ...
+ >>> default_data = {"name": "Your name", "url": "http://"}
>>> f = CommentForm(default_data, auto_id=False)
>>> print(f)
<div>Name:<input type="text" name="name" value="Your name" required></div>
@@ -206,10 +210,11 @@ validation if a particular field's value is not given. ``initial`` values are
.. code-block:: pycon
>>> class CommentForm(forms.Form):
- ... name = forms.CharField(initial='Your name')
- ... url = forms.URLField(initial='http://')
+ ... name = forms.CharField(initial="Your name")
+ ... url = forms.URLField(initial="http://")
... comment = forms.CharField()
- >>> data = {'name': '', 'url': '', 'comment': 'Foo'}
+ ...
+ >>> data = {"name": "", "url": "", "comment": "Foo"}
>>> f = CommentForm(data)
>>> f.is_valid()
False
@@ -224,6 +229,7 @@ Instead of a constant, you can also pass any callable:
>>> import datetime
>>> class DateForm(forms.Form):
... day = forms.DateField(initial=datetime.date.today)
+ ...
>>> print(DateForm())
<div><label for="id_day">Day:</label><input type="text" name="day" value="2023-02-11" required id="id_day"></div>
@@ -257,10 +263,11 @@ fields. We've specified ``auto_id=False`` to simplify the output:
>>> from django import forms
>>> class HelpTextContactForm(forms.Form):
- ... subject = forms.CharField(max_length=100, help_text='100 characters max.')
+ ... subject = forms.CharField(max_length=100, help_text="100 characters max.")
... message = forms.CharField()
- ... sender = forms.EmailField(help_text='A valid email address, please.')
+ ... sender = forms.EmailField(help_text="A valid email address, please.")
... cc_myself = forms.BooleanField(required=False)
+ ...
>>> f = HelpTextContactForm(auto_id=False)
>>> print(f)
<div>Subject:<div class="helptext">100 characters max.</div><input type="text" name="subject" maxlength="100" required></div>
@@ -281,7 +288,7 @@ want to override. For example, here is the default error message:
>>> from django import forms
>>> generic = forms.CharField()
- >>> generic.clean('')
+ >>> generic.clean("")
Traceback (most recent call last):
...
ValidationError: ['This field is required.']
@@ -290,8 +297,8 @@ And here is a custom error message:
.. code-block:: pycon
- >>> name = forms.CharField(error_messages={'required': 'Please enter your name'})
- >>> name.clean('')
+ >>> name = forms.CharField(error_messages={"required": "Please enter your name"})
+ >>> name.clean("")
Traceback (most recent call last):
...
ValidationError: ['Please enter your name']
@@ -746,12 +753,13 @@ For each field, we describe the default widget used if you don't specify
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> class ImageForm(forms.Form):
... img = forms.ImageField()
- >>> file_data = {'img': SimpleUploadedFile('test.png', b"file data")}
+ ...
+ >>> file_data = {"img": SimpleUploadedFile("test.png", b"file data")}
>>> form = ImageForm({}, file_data)
# Pillow closes the underlying file descriptor.
>>> form.is_valid()
True
- >>> image_field = form.cleaned_data['img']
+ >>> image_field = form.cleaned_data["img"]
>>> image_field.image
<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=191x287 at 0x7F5985045C18>
>>> image_field.image.width
@@ -893,9 +901,9 @@ For each field, we describe the default widget used if you don't specify
NullBooleanField(
widget=Select(
choices=[
- ('', 'Unknown'),
- (True, 'Yes'),
- (False, 'No'),
+ ("", "Unknown"),
+ (True, "Yes"),
+ (False, "No"),
]
)
)
@@ -1141,32 +1149,35 @@ Slightly complex built-in ``Field`` classes
from django.core.validators import RegexValidator
+
class PhoneField(MultiValueField):
def __init__(self, **kwargs):
# Define one message for all fields.
error_messages = {
- 'incomplete': 'Enter a country calling code and a phone number.',
+ "incomplete": "Enter a country calling code and a phone number.",
}
# Or define a different message for each field.
fields = (
CharField(
- error_messages={'incomplete': 'Enter a country calling code.'},
+ error_messages={"incomplete": "Enter a country calling code."},
validators=[
- RegexValidator(r'^[0-9]+$', 'Enter a valid country calling code.'),
+ RegexValidator(r"^[0-9]+$", "Enter a valid country calling code."),
],
),
CharField(
- error_messages={'incomplete': 'Enter a phone number.'},
- validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid phone number.')],
+ error_messages={"incomplete": "Enter a phone number."},
+ validators=[RegexValidator(r"^[0-9]+$", "Enter a valid phone number.")],
),
CharField(
- validators=[RegexValidator(r'^[0-9]+$', 'Enter a valid extension.')],
+ validators=[RegexValidator(r"^[0-9]+$", "Enter a valid extension.")],
required=False,
),
)
super().__init__(
- error_messages=error_messages, fields=fields,
- require_all_fields=False, **kwargs
+ error_messages=error_messages,
+ fields=fields,
+ require_all_fields=False,
+ **kwargs
)
.. attribute:: MultiValueField.widget
@@ -1238,7 +1249,7 @@ method::
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.fields['foo_select'].queryset = ...
+ self.fields["foo_select"].queryset = ...
Both ``ModelChoiceField`` and ``ModelMultipleChoiceField`` have an ``iterator``
attribute which specifies the class used to iterate over the queryset when
@@ -1351,6 +1362,7 @@ generating choices. See :ref:`iterating-relationship-choices` for details.
from django.forms import ModelChoiceField
+
class MyModelChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return "My Object #%i" % obj.id
@@ -1416,6 +1428,7 @@ For example, consider the following models::
from django.db import models
+
class Topping(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(decimal_places=2, max_digits=6)
@@ -1423,6 +1436,7 @@ For example, consider the following models::
def __str__(self):
return self.name
+
class Pizza(models.Model):
topping = models.ForeignKey(Topping, on_delete=models.CASCADE)
@@ -1432,18 +1446,24 @@ the value of ``Topping.price`` as the HTML attribute ``data-price`` for each
from django import forms
+
class ToppingSelect(forms.Select):
- def create_option(self, name, value, label, selected, index, subindex=None, attrs=None):
- option = super().create_option(name, value, label, selected, index, subindex, attrs)
+ def create_option(
+ self, name, value, label, selected, index, subindex=None, attrs=None
+ ):
+ option = super().create_option(
+ name, value, label, selected, index, subindex, attrs
+ )
if value:
- option['attrs']['data-price'] = value.instance.price
+ option["attrs"]["data-price"] = value.instance.price
return option
+
class PizzaForm(forms.ModelForm):
class Meta:
model = Pizza
- fields = ['topping']
- widgets = {'topping': ToppingSelect}
+ fields = ["topping"]
+ widgets = {"topping": ToppingSelect}
This will render the ``Pizza.topping`` select as:
diff --git a/docs/ref/forms/renderers.txt b/docs/ref/forms/renderers.txt
index 425594b470..6b4eb95cd7 100644
--- a/docs/ref/forms/renderers.txt
+++ b/docs/ref/forms/renderers.txt
@@ -137,7 +137,8 @@ Using this renderer along with the built-in templates requires either:
of one of your template engines. To generate that path::
import django
- django.__path__[0] + '/forms/templates' # or '/forms/jinja2'
+
+ django.__path__[0] + "/forms/templates" # or '/forms/jinja2'
Using this renderer requires you to make sure the form templates your project
needs can be located.
diff --git a/docs/ref/forms/validation.txt b/docs/ref/forms/validation.txt
index c3fa968bdb..a2b3fb4885 100644
--- a/docs/ref/forms/validation.txt
+++ b/docs/ref/forms/validation.txt
@@ -120,22 +120,22 @@ following guidelines:
* Provide a descriptive error ``code`` to the constructor::
# Good
- ValidationError(_('Invalid value'), code='invalid')
+ ValidationError(_("Invalid value"), code="invalid")
# Bad
- ValidationError(_('Invalid value'))
+ ValidationError(_("Invalid value"))
* Don't coerce variables into the message; use placeholders and the ``params``
argument of the constructor::
# Good
ValidationError(
- _('Invalid value: %(value)s'),
- params={'value': '42'},
+ _("Invalid value: %(value)s"),
+ params={"value": "42"},
)
# Bad
- ValidationError(_('Invalid value: %s') % value)
+ ValidationError(_("Invalid value: %s") % value)
* Use mapping keys instead of positional formatting. This enables putting
the variables in any order or omitting them altogether when rewriting the
@@ -143,30 +143,30 @@ following guidelines:
# Good
ValidationError(
- _('Invalid value: %(value)s'),
- params={'value': '42'},
+ _("Invalid value: %(value)s"),
+ params={"value": "42"},
)
# Bad
ValidationError(
- _('Invalid value: %s'),
- params=('42',),
+ _("Invalid value: %s"),
+ params=("42",),
)
* Wrap the message with ``gettext`` to enable translation::
# Good
- ValidationError(_('Invalid value'))
+ ValidationError(_("Invalid value"))
# Bad
- ValidationError('Invalid value')
+ ValidationError("Invalid value")
Putting it all together::
raise ValidationError(
- _('Invalid value: %(value)s'),
- code='invalid',
- params={'value': '42'},
+ _("Invalid value: %(value)s"),
+ code="invalid",
+ params={"value": "42"},
)
Following these guidelines is particularly necessary if you write reusable
@@ -176,7 +176,7 @@ While not recommended, if you are at the end of the validation chain
(i.e. your form ``clean()`` method) and you know you will *never* need
to override your error message you can still opt for the less verbose::
- ValidationError(_('Invalid value: %s') % value)
+ ValidationError(_("Invalid value: %s") % value)
The :meth:`Form.errors.as_data() <django.forms.Form.errors.as_data()>` and
:meth:`Form.errors.as_json() <django.forms.Form.errors.as_json()>` methods
@@ -194,16 +194,20 @@ As above, it is recommended to pass a list of ``ValidationError`` instances
with ``code``\s and ``params`` but a list of strings will also work::
# Good
- raise ValidationError([
- ValidationError(_('Error 1'), code='error1'),
- ValidationError(_('Error 2'), code='error2'),
- ])
+ raise ValidationError(
+ [
+ ValidationError(_("Error 1"), code="error1"),
+ ValidationError(_("Error 2"), code="error2"),
+ ]
+ )
# Bad
- raise ValidationError([
- _('Error 1'),
- _('Error 2'),
- ])
+ raise ValidationError(
+ [
+ _("Error 1"),
+ _("Error 2"),
+ ]
+ )
Using validation in practice
============================
@@ -232,6 +236,7 @@ at Django's ``SlugField``::
from django.core import validators
from django.forms import CharField
+
class SlugField(CharField):
default_validators = [validators.validate_slug]
@@ -262,13 +267,14 @@ containing comma-separated email addresses. The full class looks like this::
from django import forms
from django.core.validators import validate_email
+
class MultiEmailField(forms.Field):
def to_python(self, value):
"""Normalize data to a list of strings."""
# Return an empty list if no input was given.
if not value:
return []
- return value.split(',')
+ return value.split(",")
def validate(self, value):
"""Check if value consists only of valid emails."""
@@ -307,12 +313,13 @@ write a cleaning method that operates on the ``recipients`` field, like so::
from django import forms
from django.core.exceptions import ValidationError
+
class ContactForm(forms.Form):
# Everything as before.
...
def clean_recipients(self):
- data = self.cleaned_data['recipients']
+ data = self.cleaned_data["recipients"]
if "fred@example.com" not in data:
raise ValidationError("You have forgotten about Fred!")
@@ -349,6 +356,7 @@ example::
from django import forms
from django.core.exceptions import ValidationError
+
class ContactForm(forms.Form):
# Everything as before.
...
@@ -362,8 +370,7 @@ example::
# Only do something if both fields are valid so far.
if "help" not in subject:
raise ValidationError(
- "Did not send for 'help' in the subject despite "
- "CC'ing yourself."
+ "Did not send for 'help' in the subject despite " "CC'ing yourself."
)
In this code, if the validation error is raised, the form will display an
@@ -392,6 +399,7 @@ work out what works effectively in your particular situation. Our new code
from django import forms
+
class ContactForm(forms.Form):
# Everything as before.
...
@@ -403,8 +411,8 @@ work out what works effectively in your particular situation. Our new code
if cc_myself and subject and "help" not in subject:
msg = "Must put 'help' in subject when cc'ing yourself."
- self.add_error('cc_myself', msg)
- self.add_error('subject', msg)
+ self.add_error("cc_myself", msg)
+ self.add_error("subject", msg)
The second argument of ``add_error()`` can be a string, or preferably an
instance of ``ValidationError``. See :ref:`raising-validation-error` for more
diff --git a/docs/ref/forms/widgets.txt b/docs/ref/forms/widgets.txt
index 43a579b4a5..1fbd5ad4a0 100644
--- a/docs/ref/forms/widgets.txt
+++ b/docs/ref/forms/widgets.txt
@@ -38,6 +38,7 @@ use the :attr:`~Field.widget` argument on the field definition. For example::
from django import forms
+
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
@@ -56,15 +57,18 @@ widget on the field. In the following example, the
from django import forms
- BIRTH_YEAR_CHOICES = ['1980', '1981', '1982']
+ BIRTH_YEAR_CHOICES = ["1980", "1981", "1982"]
FAVORITE_COLORS_CHOICES = [
- ('blue', 'Blue'),
- ('green', 'Green'),
- ('black', 'Black'),
+ ("blue", "Blue"),
+ ("green", "Green"),
+ ("black", "Black"),
]
+
class SimpleForm(forms.Form):
- birth_year = forms.DateField(widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES))
+ birth_year = forms.DateField(
+ widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES)
+ )
favorite_colors = forms.MultipleChoiceField(
required=False,
widget=forms.CheckboxSelectMultiple,
@@ -91,14 +95,14 @@ example:
.. code-block:: pycon
>>> from django import forms
- >>> CHOICES = [('1', 'First'), ('2', 'Second')]
+ >>> CHOICES = [("1", "First"), ("2", "Second")]
>>> choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
>>> choice_field.choices
[('1', 'First'), ('2', 'Second')]
>>> choice_field.widget.choices
[('1', 'First'), ('2', 'Second')]
>>> choice_field.widget.choices = []
- >>> choice_field.choices = [('1', 'First and only')]
+ >>> choice_field.choices = [("1", "First and only")]
>>> choice_field.widget.choices
[('1', 'First and only')]
@@ -132,6 +136,7 @@ For example, take the following form::
from django import forms
+
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
@@ -156,9 +161,9 @@ the 'type' attribute to take advantage of the new HTML5 input types. To do
this, you use the :attr:`Widget.attrs` argument when creating the widget::
class CommentForm(forms.Form):
- name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
+ name = forms.CharField(widget=forms.TextInput(attrs={"class": "special"}))
url = forms.URLField()
- comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))
+ comment = forms.CharField(widget=forms.TextInput(attrs={"size": "40"}))
You can also modify a widget in the form definition::
@@ -167,8 +172,8 @@ You can also modify a widget in the form definition::
url = forms.URLField()
comment = forms.CharField()
- name.widget.attrs.update({'class': 'special'})
- comment.widget.attrs.update(size='40')
+ name.widget.attrs.update({"class": "special"})
+ comment.widget.attrs.update(size="40")
Or if the field isn't declared directly on the form (such as model form fields),
you can use the :attr:`Form.fields` attribute::
@@ -176,8 +181,8 @@ you can use the :attr:`Form.fields` attribute::
class CommentForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
- self.fields['name'].widget.attrs.update({'class': 'special'})
- self.fields['comment'].widget.attrs.update(size='40')
+ self.fields["name"].widget.attrs.update({"class": "special"})
+ self.fields["comment"].widget.attrs.update(size="40")
Django will then include the extra attributes in the rendered output:
@@ -231,8 +236,8 @@ foundation for custom widgets.
.. code-block:: pycon
>>> from django import forms
- >>> name = forms.TextInput(attrs={'size': 10, 'title': 'Your name'})
- >>> name.render('name', 'A name')
+ >>> name = forms.TextInput(attrs={"size": 10, "title": "Your name"})
+ >>> name.render("name", "A name")
'<input title="Your name" type="text" name="name" value="A name" size="10">'
If you assign a value of ``True`` or ``False`` to an attribute,
@@ -240,12 +245,12 @@ foundation for custom widgets.
.. code-block:: pycon
- >>> name = forms.TextInput(attrs={'required': True})
- >>> name.render('name', 'A name')
+ >>> name = forms.TextInput(attrs={"required": True})
+ >>> name.render("name", "A name")
'<input name="name" type="text" value="A name" required>'
>>>
- >>> name = forms.TextInput(attrs={'required': False})
- >>> name.render('name', 'A name')
+ >>> name = forms.TextInput(attrs={"required": False})
+ >>> name.render("name", "A name")
'<input name="name" type="text" value="A name">'
.. attribute:: Widget.supports_microseconds
@@ -373,7 +378,7 @@ foundation for custom widgets.
>>> from django.forms import MultiWidget, TextInput
>>> widget = MultiWidget(widgets=[TextInput, TextInput])
- >>> widget.render('name', ['john', 'paul'])
+ >>> widget.render("name", ["john", "paul"])
'<input type="text" name="name_0" value="john"><input type="text" name="name_1" value="paul">'
You may provide a dictionary in order to specify custom suffixes for
@@ -385,8 +390,8 @@ foundation for custom widgets.
.. code-block:: pycon
- >>> widget = MultiWidget(widgets={'': TextInput, 'last': TextInput})
- >>> widget.render('name', ['john', 'paul'])
+ >>> widget = MultiWidget(widgets={"": TextInput, "last": TextInput})
+ >>> widget.render("name", ["john", "paul"])
'<input type="text" name="name" value="john"><input type="text" name="name_last" value="paul">'
And one required method:
@@ -409,8 +414,8 @@ foundation for custom widgets.
from django.forms import MultiWidget
- class SplitDateTimeWidget(MultiWidget):
+ class SplitDateTimeWidget(MultiWidget):
# ...
def decompress(self, value):
@@ -450,6 +455,7 @@ foundation for custom widgets.
from datetime import date
from django import forms
+
class DateSelectorWidget(forms.MultiWidget):
def __init__(self, attrs=None):
days = [(day, day) for day in range(1, 32)]
@@ -466,14 +472,14 @@ foundation for custom widgets.
if isinstance(value, date):
return [value.day, value.month, value.year]
elif isinstance(value, str):
- year, month, day = value.split('-')
+ year, month, day = value.split("-")
return [day, month, year]
return [None, None, None]
def value_from_datadict(self, data, files, name):
day, month, year = super().value_from_datadict(data, files, name)
# DateField expects a single string that it can parse into a date.
- return '{}-{}-{}'.format(year, month, day)
+ return "{}-{}-{}".format(year, month, day)
The constructor creates several :class:`Select` widgets in a list. The
``super()`` method uses this list to set up the widget.
@@ -952,9 +958,18 @@ Composite widgets
the values are the displayed months::
MONTHS = {
- 1:_('jan'), 2:_('feb'), 3:_('mar'), 4:_('apr'),
- 5:_('may'), 6:_('jun'), 7:_('jul'), 8:_('aug'),
- 9:_('sep'), 10:_('oct'), 11:_('nov'), 12:_('dec')
+ 1: _("jan"),
+ 2: _("feb"),
+ 3: _("mar"),
+ 4: _("apr"),
+ 5: _("may"),
+ 6: _("jun"),
+ 7: _("jul"),
+ 8: _("aug"),
+ 9: _("sep"),
+ 10: _("oct"),
+ 11: _("nov"),
+ 12: _("dec"),
}
.. attribute:: SelectDateWidget.empty_label