Ticket #19577: 19577.2.diff

File 19577.2.diff, 5.2 KB (added by timo, 2 years ago)
  • django/utils/html.py

    diff --git a/django/utils/html.py b/django/utils/html.py
    index 25605be..ec7b28d 100644
    a b def format_html(format_string, *args, **kwargs): 
    8787
    8888def format_html_join(sep, format_string, args_generator):
    8989    """
    90     A wrapper format_html, for the common case of a group of arguments that need
    91     to be formatted using the same format string, and then joined using
     90    A wrapper of format_html, for the common case of a group of arguments that
     91    need to be formatted using the same format string, and then joined using
    9292    'sep'. 'sep' is also passed through conditional_escape.
    9393
    9494    'args_generator' should be an iterator that returns the sequence of 'args'
  • docs/ref/contrib/admin/index.txt

    diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt
    index ee04d77..a862d55 100644
    a b subclass:: 
    449449    * If the string given is a method of the model, ``ModelAdmin`` or a
    450450      callable, Django will HTML-escape the output by default. If you'd
    451451      rather not escape the output of the method, give the method an
    452       ``allow_tags`` attribute whose value is ``True``.
     452      ``allow_tags`` attribute whose value is ``True``. However, to avoid an
     453      XSS vulnerability, you should use :func:`~django.utils.html.format_html`
     454      to escape user-provided inputs.
    453455
    454456      Here's a full example model::
    455457
     458          from django.utils.html import format_html
     459
    456460          class Person(models.Model):
    457461              first_name = models.CharField(max_length=50)
    458462              last_name = models.CharField(max_length=50)
    459463              color_code = models.CharField(max_length=6)
    460464
    461465              def colored_name(self):
    462                   return '<span style="color: #%s;">%s %s</span>' % (self.color_code, self.first_name, self.last_name)
     466                  return format_html('<span style="color: #{0};">{1} {2}</span>',
     467                                     self.color_code,
     468                                     self.first_name,
     469                                     self.last_name)
     470
    463471              colored_name.allow_tags = True
    464472
    465473          class PersonAdmin(admin.ModelAdmin):
    subclass:: 
    500508
    501509      For example::
    502510
     511        from django.utils.html import format_html
     512
    503513        class Person(models.Model):
    504514            first_name = models.CharField(max_length=50)
    505515            color_code = models.CharField(max_length=6)
    506516
    507517            def colored_first_name(self):
    508                 return '<span style="color: #%s;">%s</span>' % (self.color_code, self.first_name)
     518                return format_html('<span style="color: #{0};">{1}</span>',
     519                                   self.color_code,
     520                                   self.first_name)
     521
    509522            colored_first_name.allow_tags = True
    510523            colored_first_name.admin_order_field = 'first_name'
    511524
    subclass:: 
    817830    the admin interface to provide feedback on the status of the objects being
    818831    edited, for example::
    819832
     833        from django.utils.html import format_html_join
     834        from django.utils.safestring import mark_safe
     835
    820836        class PersonAdmin(ModelAdmin):
    821837            readonly_fields = ('address_report',)
    822838
    823839            def address_report(self, instance):
    824                 return ", ".join(instance.get_full_address()) or \
    825                    "<span class='errors'>I can't determine this address.</span>"
     840                # assuming get_full_address() returns a list of strings
     841                # for each line of the address and you want to separate each
     842                # line by a linebreak
     843                return format_html_join(
     844                    mark_safe('<br/>'),
     845                    '{0}',
     846                    ((line,) for line in instance.get_full_address()),
     847                ) or "<span class='errors'>I can't determine this address.</span>"
    826848
    827849            # short_description functions like a model field's verbose_name
    828850            address_report.short_description = "Address"
    829851            # in this example, we have used HTML tags in the output
    830852            address_report.allow_tags = True
    831853
    832 
    833854.. attribute:: ModelAdmin.save_as
    834855
    835856    Set ``save_as`` to enable a "save as" feature on admin change forms.
  • docs/ref/utils.txt

    diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt
    index 20192ed..2dc007f 100644
    a b escaping HTML. 
    541541    through :func:`conditional_escape` which (ultimately) calls
    542542    :func:`~django.utils.encoding.force_text` on the values.
    543543
     544.. function:: format_html_join(sep, format_string, args_generator)
     545
     546    A wrapper of :func:`format_html`, for the common case of a group of
     547    arguments that need to be formatted using the same format string, and then
     548    joined using ``sep``. ``sep`` is also passed through
     549    :func:`conditional_escape`.
     550
     551    ``args_generator`` should be an iterator that returns the sequence of
     552    ``args`` that will be passed to :func:`format_html`. For example::
     553
     554        format_html_join('\n', "<li>{0} {1}</li>", ((u.first_name, u.last_name)
     555                                                    for u in users))
     556
     557
    544558.. function:: strip_tags(value)
    545559
    546560    Removes anything that looks like an html tag from the string, that is
Back to Top