diff options
| author | Tim Graham <timograham@gmail.com> | 2013-01-25 06:53:40 -0500 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2013-01-25 06:53:40 -0500 |
| commit | eafc0364764ba12babd76194d8e1f78b876471ec (patch) | |
| tree | 5040892ea4116794048304c7e03c6ce039dda12c /docs | |
| parent | 1f6b2e7a658594e6ae9507c5f98eb429d19c0c9d (diff) | |
Fixed #19577 - Added HTML escaping to admin examples.
Thanks foo@ for the report and Florian Apolloner for the review.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/ref/contrib/admin/index.txt | 33 | ||||
| -rw-r--r-- | docs/ref/utils.txt | 13 |
2 files changed, 40 insertions, 6 deletions
diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index ee04d77d32..a862d55875 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -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. diff --git a/docs/ref/utils.txt b/docs/ref/utils.txt index 20192ed006..e9b29602ac 100644 --- a/docs/ref/utils.txt +++ b/docs/ref/utils.txt @@ -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 |
