Commit eafc0364 authored by Tim Graham's avatar Tim Graham
Browse files

Fixed #19577 - Added HTML escaping to admin examples.

Thanks foo@ for the report and Florian Apolloner for the review.
parent 1f6b2e7a
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -87,8 +87,8 @@ def format_html(format_string, *args, **kwargs):

def format_html_join(sep, format_string, args_generator):
    """
    A wrapper format_html, for the common case of a group of arguments that need
    to be formatted using the same format string, and then joined using
    A wrapper of format_html, for the common case of a group of arguments that
    need to be formatted using the same format string, and then joined using
    'sep'. 'sep' is also passed through conditional_escape.

    'args_generator' should be an iterator that returns the sequence of 'args'
+27 −6
Original line number Diff line number Diff line
@@ -449,17 +449,25 @@ subclass::
    * If the string given is a method of the model, ``ModelAdmin`` or a
      callable, Django will HTML-escape the output by default. If you'd
      rather not escape the output of the method, give the method an
      ``allow_tags`` attribute whose value is ``True``.
      ``allow_tags`` attribute whose value is ``True``. However, to avoid an
      XSS vulnerability, you should use :func:`~django.utils.html.format_html`
      to escape user-provided inputs.

      Here's a full example model::

          from django.utils.html import format_html

          class Person(models.Model):
              first_name = models.CharField(max_length=50)
              last_name = models.CharField(max_length=50)
              color_code = models.CharField(max_length=6)

              def colored_name(self):
                  return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
                  return format_html('<span style="color: #{0};">{1} {2}</span>',
                                     self.color_code,
                                     self.first_name,
                                     self.last_name)

              colored_name.allow_tags = True

          class PersonAdmin(admin.ModelAdmin):
@@ -500,12 +508,17 @@ subclass::

      For example::

        from django.utils.html import format_html

        class Person(models.Model):
            first_name = models.CharField(max_length=50)
            color_code = models.CharField(max_length=6)

            def colored_first_name(self):
                return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
                return format_html('<span style="color: #{0};">{1}</span>',
                                   self.color_code,
                                   self.first_name)

            colored_first_name.allow_tags = True
            colored_first_name.admin_order_field = 'first_name'

@@ -817,19 +830,27 @@ subclass::
    the admin interface to provide feedback on the status of the objects being
    edited, for example::

        from django.utils.html import format_html_join
        from django.utils.safestring import mark_safe

        class PersonAdmin(ModelAdmin):
            readonly_fields = ('address_report',)

            def address_report(self, instance):
                return ", ".join(instance.get_full_address()) or \
                   "<span class='errors'>I can't determine this address.</span>"
                # assuming get_full_address() returns a list of strings
                # for each line of the address and you want to separate each
                # line by a linebreak
                return format_html_join(
                    mark_safe('<br/>'),
                    '{0}',
                    ((line,) for line in instance.get_full_address()),
                ) or "<span class='errors'>I can't determine this address.</span>"

            # short_description functions like a model field's verbose_name
            address_report.short_description = "Address"
            # in this example, we have used HTML tags in the output
            address_report.allow_tags = True


.. attribute:: ModelAdmin.save_as

    Set ``save_as`` to enable a "save as" feature on admin change forms.
+13 −0
Original line number Diff line number Diff line
@@ -541,6 +541,19 @@ escaping HTML.
    through :func:`conditional_escape` which (ultimately) calls
    :func:`~django.utils.encoding.force_text` on the values.

.. function:: format_html_join(sep, format_string, args_generator)

    A wrapper of :func:`format_html`, for the common case of a group of
    arguments that need to be formatted using the same format string, and then
    joined using ``sep``. ``sep`` is also passed through
    :func:`conditional_escape`.

    ``args_generator`` should be an iterator that returns the sequence of
    ``args`` that will be passed to :func:`format_html`. For example::

        format_html_join('\n', "<li>{0} {1}</li>", ((u.first_name, u.last_name)
                                                    for u in users))

.. function:: strip_tags(value)

    Removes anything that looks like an html tag from the string, that is