Commit 4f163762 authored by Claude Paroz's avatar Claude Paroz
Browse files

Added HTML5 email input type

Refs #16630.
parent c47fa3b4
Loading
Loading
Loading
Loading
+5 −2
Original line number Diff line number Diff line
@@ -18,10 +18,12 @@ from io import BytesIO
from django.core import validators
from django.core.exceptions import ValidationError
from django.forms.util import ErrorList, from_current_timezone, to_current_timezone
from django.forms.widgets import (TextInput, PasswordInput, HiddenInput,
from django.forms.widgets import (
    TextInput, PasswordInput, EmailInput, HiddenInput,
    MultipleHiddenInput, ClearableFileInput, CheckboxInput, Select,
    NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput,
    SplitDateTimeWidget, SplitHiddenDateTimeWidget, FILE_INPUT_CONTRADICTION)
    SplitDateTimeWidget, SplitHiddenDateTimeWidget, FILE_INPUT_CONTRADICTION
)
from django.utils import formats
from django.utils.encoding import smart_text, force_str, force_text
from django.utils.ipv6 import clean_ipv6_address
@@ -487,6 +489,7 @@ class RegexField(CharField):
    regex = property(_get_regex, _set_regex)

class EmailField(CharField):
    widget = EmailInput
    default_error_messages = {
        'invalid': _('Enter a valid email address.'),
    }
+5 −1
Original line number Diff line number Diff line
@@ -22,7 +22,7 @@ from django.utils.safestring import mark_safe
from django.utils import datetime_safe, formats, six

__all__ = (
    'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'PasswordInput',
    'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'EmailInput', 'PasswordInput',
    'HiddenInput', 'MultipleHiddenInput', 'ClearableFileInput',
    'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput',
    'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect',
@@ -251,6 +251,10 @@ class TextInput(Input):
        super(TextInput, self).__init__(attrs)


class EmailInput(TextInput):
    input_type = 'email'


class PasswordInput(TextInput):
    input_type = 'password'

+27 −26
Original line number Diff line number Diff line
@@ -270,7 +270,7 @@ simply ``print`` it::
    >>> print(f)
    <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
    <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
    <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
    <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>
    <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>

If the form is bound to data, the HTML output will include that data
@@ -287,7 +287,7 @@ include ``checked="checked"`` if appropriate::
    >>> print(f)
    <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" value="hello" /></td></tr>
    <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" value="Hi there" /></td></tr>
    <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
    <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" value="foo@example.com" /></td></tr>
    <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" checked="checked" /></td></tr>

This default output is a two-column HTML table, with a ``<tr>`` for each field.
@@ -297,8 +297,9 @@ Notice the following:
  ``</table>`` tags, nor does it include the ``<form>`` and ``</form>``
  tags or an ``<input type="submit">`` tag. It's your job to do that.

* Each field type has a default HTML representation. ``CharField`` and
  ``EmailField`` are represented by an ``<input type="text">``.
* Each field type has a default HTML representation. ``CharField`` is
  represented by an ``<input type="text">`` and ``EmailField`` by an
  ``<input type="email">``.
  ``BooleanField`` is represented by an ``<input type="checkbox">``. Note
  these are merely sensible defaults; you can specify which HTML to use for
  a given field by using widgets, which we'll explain shortly.
@@ -335,7 +336,7 @@ a form object, and each rendering method returns a Unicode object.
        >>> print(f.as_p())
        <p><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></p>
        <p><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></p>
        <p><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></p>
        <p><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></p>
        <p><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></p>

``as_ul()``
@@ -350,11 +351,11 @@ a form object, and each rendering method returns a Unicode object.

        >>> f = ContactForm()
        >>> f.as_ul()
        u'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
        u'<li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>\n<li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>\n<li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></li>\n<li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>'
        >>> print(f.as_ul())
        <li><label for="id_subject">Subject:</label> <input id="id_subject" type="text" name="subject" maxlength="100" /></li>
        <li><label for="id_message">Message:</label> <input type="text" name="message" id="id_message" /></li>
        <li><label for="id_sender">Sender:</label> <input type="text" name="sender" id="id_sender" /></li>
        <li><label for="id_sender">Sender:</label> <input type="email" name="sender" id="id_sender" /></li>
        <li><label for="id_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_cc_myself" /></li>

``as_table()``
@@ -368,11 +369,11 @@ a form object, and each rendering method returns a Unicode object.

        >>> f = ContactForm()
        >>> f.as_table()
        u'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
        u'<tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>\n<tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>\n<tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>\n<tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>'
        >>> print(f.as_table())
        <tr><th><label for="id_subject">Subject:</label></th><td><input id="id_subject" type="text" name="subject" maxlength="100" /></td></tr>
        <tr><th><label for="id_message">Message:</label></th><td><input type="text" name="message" id="id_message" /></td></tr>
        <tr><th><label for="id_sender">Sender:</label></th><td><input type="text" name="sender" id="id_sender" /></td></tr>
        <tr><th><label for="id_sender">Sender:</label></th><td><input type="email" name="sender" id="id_sender" /></td></tr>
        <tr><th><label for="id_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_cc_myself" /></td></tr>

Styling required or erroneous form rows
@@ -431,17 +432,17 @@ tags nor ``id`` attributes::
    >>> print(f.as_table())
    <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /></td></tr>
    <tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
    <tr><th>Sender:</th><td><input type="text" name="sender" /></td></tr>
    <tr><th>Sender:</th><td><input type="email" name="sender" /></td></tr>
    <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
    >>> print(f.as_ul())
    <li>Subject: <input type="text" name="subject" maxlength="100" /></li>
    <li>Message: <input type="text" name="message" /></li>
    <li>Sender: <input type="text" name="sender" /></li>
    <li>Sender: <input type="email" name="sender" /></li>
    <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
    >>> print(f.as_p())
    <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
    <p>Message: <input type="text" name="message" /></p>
    <p>Sender: <input type="text" name="sender" /></p>
    <p>Sender: <input type="email" name="sender" /></p>
    <p>Cc myself: <input type="checkbox" name="cc_myself" /></p>

If ``auto_id`` is set to ``True``, then the form output *will* include
@@ -452,17 +453,17 @@ field::
    >>> print(f.as_table())
    <tr><th><label for="subject">Subject:</label></th><td><input id="subject" type="text" name="subject" maxlength="100" /></td></tr>
    <tr><th><label for="message">Message:</label></th><td><input type="text" name="message" id="message" /></td></tr>
    <tr><th><label for="sender">Sender:</label></th><td><input type="text" name="sender" id="sender" /></td></tr>
    <tr><th><label for="sender">Sender:</label></th><td><input type="email" name="sender" id="sender" /></td></tr>
    <tr><th><label for="cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="cc_myself" /></td></tr>
    >>> print(f.as_ul())
    <li><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></li>
    <li><label for="message">Message:</label> <input type="text" name="message" id="message" /></li>
    <li><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></li>
    <li><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" /></li>
    <li><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></li>
    >>> print(f.as_p())
    <p><label for="subject">Subject:</label> <input id="subject" type="text" name="subject" maxlength="100" /></p>
    <p><label for="message">Message:</label> <input type="text" name="message" id="message" /></p>
    <p><label for="sender">Sender:</label> <input type="text" name="sender" id="sender" /></p>
    <p><label for="sender">Sender:</label> <input type="email" name="sender" id="sender" /></p>
    <p><label for="cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="cc_myself" /></p>

If ``auto_id`` is set to a string containing the format character ``'%s'``,
@@ -475,17 +476,17 @@ attributes based on the format string. For example, for a format string
    >>> print(f.as_table())
    <tr><th><label for="id_for_subject">Subject:</label></th><td><input id="id_for_subject" type="text" name="subject" maxlength="100" /></td></tr>
    <tr><th><label for="id_for_message">Message:</label></th><td><input type="text" name="message" id="id_for_message" /></td></tr>
    <tr><th><label for="id_for_sender">Sender:</label></th><td><input type="text" name="sender" id="id_for_sender" /></td></tr>
    <tr><th><label for="id_for_sender">Sender:</label></th><td><input type="email" name="sender" id="id_for_sender" /></td></tr>
    <tr><th><label for="id_for_cc_myself">Cc myself:</label></th><td><input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></td></tr>
    >>> print(f.as_ul())
    <li><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
    <li><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></li>
    <li><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></li>
    <li><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" /></li>
    <li><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
    >>> print(f.as_p())
    <p><label for="id_for_subject">Subject:</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></p>
    <p><label for="id_for_message">Message:</label> <input type="text" name="message" id="id_for_message" /></p>
    <p><label for="id_for_sender">Sender:</label> <input type="text" name="sender" id="id_for_sender" /></p>
    <p><label for="id_for_sender">Sender:</label> <input type="email" name="sender" id="id_for_sender" /></p>
    <p><label for="id_for_cc_myself">Cc myself:</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></p>

If ``auto_id`` is set to any other true value -- such as a string that doesn't
@@ -501,13 +502,13 @@ entirely, using the ``label_suffix`` parameter::
    >>> print(f.as_ul())
    <li><label for="id_for_subject">Subject</label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
    <li><label for="id_for_message">Message</label> <input type="text" name="message" id="id_for_message" /></li>
    <li><label for="id_for_sender">Sender</label> <input type="text" name="sender" id="id_for_sender" /></li>
    <li><label for="id_for_sender">Sender</label> <input type="email" name="sender" id="id_for_sender" /></li>
    <li><label for="id_for_cc_myself">Cc myself</label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>
    >>> f = ContactForm(auto_id='id_for_%s', label_suffix=' ->')
    >>> print(f.as_ul())
    <li><label for="id_for_subject">Subject -></label> <input id="id_for_subject" type="text" name="subject" maxlength="100" /></li>
    <li><label for="id_for_message">Message -></label> <input type="text" name="message" id="id_for_message" /></li>
    <li><label for="id_for_sender">Sender -></label> <input type="text" name="sender" id="id_for_sender" /></li>
    <li><label for="id_for_sender">Sender -></label> <input type="email" name="sender" id="id_for_sender" /></li>
    <li><label for="id_for_cc_myself">Cc myself -></label> <input type="checkbox" name="cc_myself" id="id_for_cc_myself" /></li>

Note that the label suffix is added only if the last character of the
@@ -539,19 +540,19 @@ method you're using::
    >>> print(f.as_table())
    <tr><th>Subject:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="subject" maxlength="100" /></td></tr>
    <tr><th>Message:</th><td><input type="text" name="message" value="Hi there" /></td></tr>
    <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="text" name="sender" value="invalid email address" /></td></tr>
    <tr><th>Sender:</th><td><ul class="errorlist"><li>Enter a valid email address.</li></ul><input type="email" name="sender" value="invalid email address" /></td></tr>
    <tr><th>Cc myself:</th><td><input checked="checked" type="checkbox" name="cc_myself" /></td></tr>
    >>> print(f.as_ul())
    <li><ul class="errorlist"><li>This field is required.</li></ul>Subject: <input type="text" name="subject" maxlength="100" /></li>
    <li>Message: <input type="text" name="message" value="Hi there" /></li>
    <li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="text" name="sender" value="invalid email address" /></li>
    <li><ul class="errorlist"><li>Enter a valid email address.</li></ul>Sender: <input type="email" name="sender" value="invalid email address" /></li>
    <li>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></li>
    >>> print(f.as_p())
    <p><ul class="errorlist"><li>This field is required.</li></ul></p>
    <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
    <p>Message: <input type="text" name="message" value="Hi there" /></p>
    <p><ul class="errorlist"><li>Enter a valid email address.</li></ul></p>
    <p>Sender: <input type="text" name="sender" value="invalid email address" /></p>
    <p>Sender: <input type="email" name="sender" value="invalid email address" /></p>
    <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>

Customizing the error list format
@@ -574,7 +575,7 @@ pass that in at construction time::
    <p>Subject: <input type="text" name="subject" maxlength="100" /></p>
    <p>Message: <input type="text" name="message" value="Hi there" /></p>
    <div class="errorlist"><div class="error">Enter a valid email address.</div></div>
    <p>Sender: <input type="text" name="sender" value="invalid email address" /></p>
    <p>Sender: <input type="email" name="sender" value="invalid email address" /></p>
    <p>Cc myself: <input checked="checked" type="checkbox" name="cc_myself" /></p>

More granular output
@@ -604,7 +605,7 @@ To retrieve all ``BoundField`` objects, iterate the form::
    >>> for boundfield in form: print(boundfield)
    <input id="id_subject" type="text" name="subject" maxlength="100" />
    <input type="text" name="message" id="id_message" />
    <input type="text" name="sender" id="id_sender" />
    <input type="email" name="sender" id="id_sender" />
    <input type="checkbox" name="cc_myself" id="id_cc_myself" />

The field-specific output honors the form object's ``auto_id`` setting::
@@ -756,7 +757,7 @@ fields are ordered first::
    >>> print(f.as_ul())
    <li>Subject: <input type="text" name="subject" maxlength="100" /></li>
    <li>Message: <input type="text" name="message" /></li>
    <li>Sender: <input type="text" name="sender" /></li>
    <li>Sender: <input type="email" name="sender" /></li>
    <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
    <li>Priority: <input type="text" name="priority" /></li>

+4 −4
Original line number Diff line number Diff line
@@ -212,17 +212,17 @@ fields. We've specified ``auto_id=False`` to simplify the output::
    >>> print(f.as_table())
    <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" /><br /><span class="helptext">100 characters max.</span></td></tr>
    <tr><th>Message:</th><td><input type="text" name="message" /></td></tr>
    <tr><th>Sender:</th><td><input type="text" name="sender" /><br />A valid email address, please.</td></tr>
    <tr><th>Sender:</th><td><input type="email" name="sender" /><br />A valid email address, please.</td></tr>
    <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
    >>> print(f.as_ul()))
    <li>Subject: <input type="text" name="subject" maxlength="100" /> <span class="helptext">100 characters max.</span></li>
    <li>Message: <input type="text" name="message" /></li>
    <li>Sender: <input type="text" name="sender" /> A valid email address, please.</li>
    <li>Sender: <input type="email" name="sender" /> A valid email address, please.</li>
    <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
    >>> print(f.as_p())
    <p>Subject: <input type="text" name="subject" maxlength="100" /> <span class="helptext">100 characters max.</span></p>
    <p>Message: <input type="text" name="message" /></p>
    <p>Sender: <input type="text" name="sender" /> A valid email address, please.</p>
    <p>Sender: <input type="email" name="sender" /> A valid email address, please.</p>
    <p>Cc myself: <input type="checkbox" name="cc_myself" /></p>

``error_messages``
@@ -489,7 +489,7 @@ For each field, we describe the default widget used if you don't specify

.. class:: EmailField(**kwargs)

    * Default widget: :class:`TextInput`
    * Default widget: :class:`EmailInput`
    * Empty value: ``''`` (an empty string)
    * Normalizes to: A Unicode object.
    * Validates that the given value is a valid email address, using a
+10 −1
Original line number Diff line number Diff line
@@ -392,7 +392,16 @@ These widgets make use of the HTML elements ``input`` and ``textarea``.

.. class:: TextInput

    Text input: ``<input type='text' ...>``
    Text input: ``<input type="text" ...>``

``EmailInput``
~~~~~~~~~~~~~~

.. class:: EmailInput

    .. versionadded:: 1.6

    Text input: ``<input type="email" ...>``

``PasswordInput``
~~~~~~~~~~~~~~~~~
Loading