Fixed #19577 - Added HTML escaping to admin examples.
Thanks foo@ for the report and Florian Apolloner for the review.
This commit is contained in:
parent
1f6b2e7a65
commit
eafc036476
|
@ -87,8 +87,8 @@ def format_html(format_string, *args, **kwargs):
|
||||||
|
|
||||||
def format_html_join(sep, format_string, args_generator):
|
def format_html_join(sep, format_string, args_generator):
|
||||||
"""
|
"""
|
||||||
A wrapper format_html, for the common case of a group of arguments that need
|
A wrapper of format_html, for the common case of a group of arguments that
|
||||||
to be formatted using the same format string, and then joined using
|
need to be formatted using the same format string, and then joined using
|
||||||
'sep'. 'sep' is also passed through conditional_escape.
|
'sep'. 'sep' is also passed through conditional_escape.
|
||||||
|
|
||||||
'args_generator' should be an iterator that returns the sequence of 'args'
|
'args_generator' should be an iterator that returns the sequence of 'args'
|
||||||
|
|
|
@ -449,17 +449,25 @@ subclass::
|
||||||
* If the string given is a method of the model, ``ModelAdmin`` or a
|
* 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
|
callable, Django will HTML-escape the output by default. If you'd
|
||||||
rather not escape the output of the method, give the method an
|
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::
|
Here's a full example model::
|
||||||
|
|
||||||
|
from django.utils.html import format_html
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
first_name = models.CharField(max_length=50)
|
first_name = models.CharField(max_length=50)
|
||||||
last_name = models.CharField(max_length=50)
|
last_name = models.CharField(max_length=50)
|
||||||
color_code = models.CharField(max_length=6)
|
color_code = models.CharField(max_length=6)
|
||||||
|
|
||||||
def colored_name(self):
|
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
|
colored_name.allow_tags = True
|
||||||
|
|
||||||
class PersonAdmin(admin.ModelAdmin):
|
class PersonAdmin(admin.ModelAdmin):
|
||||||
|
@ -500,12 +508,17 @@ subclass::
|
||||||
|
|
||||||
For example::
|
For example::
|
||||||
|
|
||||||
|
from django.utils.html import format_html
|
||||||
|
|
||||||
class Person(models.Model):
|
class Person(models.Model):
|
||||||
first_name = models.CharField(max_length=50)
|
first_name = models.CharField(max_length=50)
|
||||||
color_code = models.CharField(max_length=6)
|
color_code = models.CharField(max_length=6)
|
||||||
|
|
||||||
def colored_first_name(self):
|
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.allow_tags = True
|
||||||
colored_first_name.admin_order_field = 'first_name'
|
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
|
the admin interface to provide feedback on the status of the objects being
|
||||||
edited, for example::
|
edited, for example::
|
||||||
|
|
||||||
|
from django.utils.html import format_html_join
|
||||||
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
class PersonAdmin(ModelAdmin):
|
class PersonAdmin(ModelAdmin):
|
||||||
readonly_fields = ('address_report',)
|
readonly_fields = ('address_report',)
|
||||||
|
|
||||||
def address_report(self, instance):
|
def address_report(self, instance):
|
||||||
return ", ".join(instance.get_full_address()) or \
|
# assuming get_full_address() returns a list of strings
|
||||||
"<span class='errors'>I can't determine this address.</span>"
|
# 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
|
# short_description functions like a model field's verbose_name
|
||||||
address_report.short_description = "Address"
|
address_report.short_description = "Address"
|
||||||
# in this example, we have used HTML tags in the output
|
# in this example, we have used HTML tags in the output
|
||||||
address_report.allow_tags = True
|
address_report.allow_tags = True
|
||||||
|
|
||||||
|
|
||||||
.. attribute:: ModelAdmin.save_as
|
.. attribute:: ModelAdmin.save_as
|
||||||
|
|
||||||
Set ``save_as`` to enable a "save as" feature on admin change forms.
|
Set ``save_as`` to enable a "save as" feature on admin change forms.
|
||||||
|
|
|
@ -541,6 +541,19 @@ escaping HTML.
|
||||||
through :func:`conditional_escape` which (ultimately) calls
|
through :func:`conditional_escape` which (ultimately) calls
|
||||||
:func:`~django.utils.encoding.force_text` on the values.
|
: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)
|
.. function:: strip_tags(value)
|
||||||
|
|
||||||
Removes anything that looks like an html tag from the string, that is
|
Removes anything that looks like an html tag from the string, that is
|
||||||
|
|
Loading…
Reference in New Issue