Changed a lot of internal code to use 'format_html' where appropriate/possible
This commit is contained in:
parent
bee498f3a2
commit
a92e7f37c4
|
@ -10,7 +10,7 @@ from django.db.models.fields.related import ManyToManyRel
|
||||||
from django.forms.util import flatatt
|
from django.forms.util import flatatt
|
||||||
from django.template.defaultfilters import capfirst
|
from django.template.defaultfilters import capfirst
|
||||||
from django.utils.encoding import force_unicode, smart_unicode
|
from django.utils.encoding import force_unicode, smart_unicode
|
||||||
from django.utils.html import escape, conditional_escape
|
from django.utils.html import conditional_escape, format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
@ -163,11 +163,9 @@ class AdminReadonlyField(object):
|
||||||
if not self.is_first:
|
if not self.is_first:
|
||||||
attrs["class"] = "inline"
|
attrs["class"] = "inline"
|
||||||
label = self.field['label']
|
label = self.field['label']
|
||||||
contents = capfirst(force_unicode(escape(label))) + ":"
|
return format_html('<label{0}>{1}:</label>',
|
||||||
return mark_safe('<label%(attrs)s>%(contents)s</label>' % {
|
flatatt(attrs),
|
||||||
"attrs": flatatt(attrs),
|
capfirst(force_unicode(label)))
|
||||||
"contents": contents,
|
|
||||||
})
|
|
||||||
|
|
||||||
def contents(self):
|
def contents(self):
|
||||||
from django.contrib.admin.templatetags.admin_list import _boolean_icon
|
from django.contrib.admin.templatetags.admin_list import _boolean_icon
|
||||||
|
|
|
@ -10,7 +10,7 @@ from django.contrib.admin.templatetags.admin_static import static
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
from django.utils.html import escape, conditional_escape
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
@ -31,9 +31,12 @@ def paginator_number(cl,i):
|
||||||
if i == DOT:
|
if i == DOT:
|
||||||
return '... '
|
return '... '
|
||||||
elif i == cl.page_num:
|
elif i == cl.page_num:
|
||||||
return mark_safe('<span class="this-page">%d</span> ' % (i+1))
|
return format_html('<span class="this-page">{}</span> ', i+1)
|
||||||
else:
|
else:
|
||||||
return mark_safe('<a href="%s"%s>%d</a> ' % (escape(cl.get_query_string({PAGE_VAR: i})), (i == cl.paginator.num_pages-1 and ' class="end"' or ''), i+1))
|
return format_html('<a href="{0}"{1}>{2}</a> ',
|
||||||
|
cl.get_query_string({PAGE_VAR: i}),
|
||||||
|
mark_safe(' class="end"' if i == cl.paginator.num_pages-1 else ''),
|
||||||
|
i+1)
|
||||||
|
|
||||||
@register.inclusion_tag('admin/pagination.html')
|
@register.inclusion_tag('admin/pagination.html')
|
||||||
def pagination(cl):
|
def pagination(cl):
|
||||||
|
@ -159,13 +162,14 @@ def result_headers(cl):
|
||||||
"url_primary": cl.get_query_string({ORDER_VAR: '.'.join(o_list_primary)}),
|
"url_primary": cl.get_query_string({ORDER_VAR: '.'.join(o_list_primary)}),
|
||||||
"url_remove": cl.get_query_string({ORDER_VAR: '.'.join(o_list_remove)}),
|
"url_remove": cl.get_query_string({ORDER_VAR: '.'.join(o_list_remove)}),
|
||||||
"url_toggle": cl.get_query_string({ORDER_VAR: '.'.join(o_list_toggle)}),
|
"url_toggle": cl.get_query_string({ORDER_VAR: '.'.join(o_list_toggle)}),
|
||||||
"class_attrib": mark_safe(th_classes and ' class="%s"' % ' '.join(th_classes) or '')
|
"class_attrib": format_html(' class="{}"', ' '.join(th_classes))
|
||||||
|
if th_classes else '',
|
||||||
}
|
}
|
||||||
|
|
||||||
def _boolean_icon(field_val):
|
def _boolean_icon(field_val):
|
||||||
icon_url = static('admin/img/icon-%s.gif' %
|
icon_url = static('admin/img/icon-%s.gif' %
|
||||||
{True: 'yes', False: 'no', None: 'unknown'}[field_val])
|
{True: 'yes', False: 'no', None: 'unknown'}[field_val])
|
||||||
return mark_safe('<img src="%s" alt="%s" />' % (icon_url, field_val))
|
return format_html('<img src="{0}" alt="{1}" />', icon_url, field_val)
|
||||||
|
|
||||||
def items_for_result(cl, result, form):
|
def items_for_result(cl, result, form):
|
||||||
"""
|
"""
|
||||||
|
@ -182,7 +186,7 @@ def items_for_result(cl, result, form):
|
||||||
else:
|
else:
|
||||||
if f is None:
|
if f is None:
|
||||||
if field_name == 'action_checkbox':
|
if field_name == 'action_checkbox':
|
||||||
row_class = ' class="action-checkbox"'
|
row_class = mark_safe(' class="action-checkbox"')
|
||||||
allow_tags = getattr(attr, 'allow_tags', False)
|
allow_tags = getattr(attr, 'allow_tags', False)
|
||||||
boolean = getattr(attr, 'boolean', False)
|
boolean = getattr(attr, 'boolean', False)
|
||||||
if boolean:
|
if boolean:
|
||||||
|
@ -190,23 +194,21 @@ def items_for_result(cl, result, form):
|
||||||
result_repr = display_for_value(value, boolean)
|
result_repr = display_for_value(value, boolean)
|
||||||
# Strip HTML tags in the resulting text, except if the
|
# Strip HTML tags in the resulting text, except if the
|
||||||
# function has an "allow_tags" attribute set to True.
|
# function has an "allow_tags" attribute set to True.
|
||||||
if not allow_tags:
|
if allow_tags:
|
||||||
result_repr = escape(result_repr)
|
|
||||||
else:
|
|
||||||
result_repr = mark_safe(result_repr)
|
result_repr = mark_safe(result_repr)
|
||||||
if isinstance(value, (datetime.date, datetime.time)):
|
if isinstance(value, (datetime.date, datetime.time)):
|
||||||
row_class = ' class="nowrap"'
|
row_class = mark_safe(' class="nowrap"')
|
||||||
else:
|
else:
|
||||||
if isinstance(f.rel, models.ManyToOneRel):
|
if isinstance(f.rel, models.ManyToOneRel):
|
||||||
field_val = getattr(result, f.name)
|
field_val = getattr(result, f.name)
|
||||||
if field_val is None:
|
if field_val is None:
|
||||||
result_repr = EMPTY_CHANGELIST_VALUE
|
result_repr = EMPTY_CHANGELIST_VALUE
|
||||||
else:
|
else:
|
||||||
result_repr = escape(field_val)
|
result_repr = field_val
|
||||||
else:
|
else:
|
||||||
result_repr = display_for_field(value, f)
|
result_repr = display_for_field(value, f)
|
||||||
if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
|
if isinstance(f, (models.DateField, models.TimeField, models.ForeignKey)):
|
||||||
row_class = ' class="nowrap"'
|
row_class = mark_safe(' class="nowrap"')
|
||||||
if force_unicode(result_repr) == '':
|
if force_unicode(result_repr) == '':
|
||||||
result_repr = mark_safe(' ')
|
result_repr = mark_safe(' ')
|
||||||
# If list_display_links not defined, add the link tag to the first field
|
# If list_display_links not defined, add the link tag to the first field
|
||||||
|
@ -222,8 +224,14 @@ def items_for_result(cl, result, form):
|
||||||
attr = pk
|
attr = pk
|
||||||
value = result.serializable_value(attr)
|
value = result.serializable_value(attr)
|
||||||
result_id = repr(force_unicode(value))[1:]
|
result_id = repr(force_unicode(value))[1:]
|
||||||
yield mark_safe('<%s%s><a href="%s"%s>%s</a></%s>' % \
|
yield format_html('<{0}{1}><a href="{2}"{3}>{4}</a></{5}>',
|
||||||
(table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %s); return false;"' % result_id or ''), conditional_escape(result_repr), table_tag))
|
table_tag,
|
||||||
|
row_class,
|
||||||
|
url,
|
||||||
|
format_html(' onclick="opener.dismissRelatedLookupPopup(window, {0}); return false;"', result_id)
|
||||||
|
if cl.is_popup else '',
|
||||||
|
result_repr,
|
||||||
|
table_tag)
|
||||||
else:
|
else:
|
||||||
# By default the fields come from ModelAdmin.list_editable, but if we pull
|
# By default the fields come from ModelAdmin.list_editable, but if we pull
|
||||||
# the fields out of the form instead of list_editable custom admins
|
# the fields out of the form instead of list_editable custom admins
|
||||||
|
@ -233,11 +241,9 @@ def items_for_result(cl, result, form):
|
||||||
form[cl.model._meta.pk.name].is_hidden)):
|
form[cl.model._meta.pk.name].is_hidden)):
|
||||||
bf = form[field_name]
|
bf = form[field_name]
|
||||||
result_repr = mark_safe(force_unicode(bf.errors) + force_unicode(bf))
|
result_repr = mark_safe(force_unicode(bf.errors) + force_unicode(bf))
|
||||||
else:
|
yield format_html('<td{0}>{1}</td>', row_class, result_repr)
|
||||||
result_repr = conditional_escape(result_repr)
|
|
||||||
yield mark_safe('<td%s>%s</td>' % (row_class, result_repr))
|
|
||||||
if form and not form[cl.model._meta.pk.name].is_hidden:
|
if form and not form[cl.model._meta.pk.name].is_hidden:
|
||||||
yield mark_safe('<td>%s</td>' % force_unicode(form[cl.model._meta.pk.name]))
|
yield format_html('<td>{0}</td>', force_unicode(form[cl.model._meta.pk.name]))
|
||||||
|
|
||||||
class ResultList(list):
|
class ResultList(list):
|
||||||
# Wrapper class used to return items in a list_editable
|
# Wrapper class used to return items in a list_editable
|
||||||
|
|
|
@ -9,8 +9,7 @@ from django.db.models.deletion import Collector
|
||||||
from django.db.models.related import RelatedObject
|
from django.db.models.related import RelatedObject
|
||||||
from django.forms.forms import pretty_name
|
from django.forms.forms import pretty_name
|
||||||
from django.utils import formats
|
from django.utils import formats
|
||||||
from django.utils.html import escape
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from django.utils.encoding import force_unicode, smart_unicode, smart_str
|
from django.utils.encoding import force_unicode, smart_unicode, smart_str
|
||||||
|
@ -124,10 +123,10 @@ def get_deleted_objects(objs, opts, user, admin_site, using):
|
||||||
if not user.has_perm(p):
|
if not user.has_perm(p):
|
||||||
perms_needed.add(opts.verbose_name)
|
perms_needed.add(opts.verbose_name)
|
||||||
# Display a link to the admin page.
|
# Display a link to the admin page.
|
||||||
return mark_safe('%s: <a href="%s">%s</a>' %
|
return format_html('{0}: <a href="{1}">{2}</a>',
|
||||||
(escape(capfirst(opts.verbose_name)),
|
capfirst(opts.verbose_name),
|
||||||
admin_url,
|
admin_url,
|
||||||
escape(obj)))
|
obj)
|
||||||
else:
|
else:
|
||||||
# Don't display link to edit, because it either has no
|
# Don't display link to edit, because it either has no
|
||||||
# admin or is edited inline.
|
# admin or is edited inline.
|
||||||
|
|
|
@ -10,7 +10,7 @@ from django.contrib.admin.templatetags.admin_static import static
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.forms.widgets import RadioFieldRenderer
|
from django.forms.widgets import RadioFieldRenderer
|
||||||
from django.forms.util import flatatt
|
from django.forms.util import flatatt
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape, format_html, format_html_join
|
||||||
from django.utils.text import Truncator
|
from django.utils.text import Truncator
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -85,16 +85,17 @@ class AdminSplitDateTime(forms.SplitDateTimeWidget):
|
||||||
forms.MultiWidget.__init__(self, widgets, attrs)
|
forms.MultiWidget.__init__(self, widgets, attrs)
|
||||||
|
|
||||||
def format_output(self, rendered_widgets):
|
def format_output(self, rendered_widgets):
|
||||||
return mark_safe('<p class="datetime">%s %s<br />%s %s</p>' % \
|
return format_html('<p class="datetime">{0} {1}<br />{2} {3}</p>',
|
||||||
(_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]))
|
_('Date:'), rendered_widgets[0],
|
||||||
|
_('Time:'), rendered_widgets[1])
|
||||||
|
|
||||||
class AdminRadioFieldRenderer(RadioFieldRenderer):
|
class AdminRadioFieldRenderer(RadioFieldRenderer):
|
||||||
def render(self):
|
def render(self):
|
||||||
"""Outputs a <ul> for this set of radio fields."""
|
"""Outputs a <ul> for this set of radio fields."""
|
||||||
return mark_safe('<ul%s>\n%s\n</ul>' % (
|
return format_html('<ul{0}>\n{1}\n</ul>',
|
||||||
flatatt(self.attrs),
|
flatatt(self.attrs),
|
||||||
'\n'.join(['<li>%s</li>' % force_unicode(w) for w in self]))
|
format_html_join('\n', '<li>{0}</li>',
|
||||||
)
|
((force_unicode(w),) for w in self)))
|
||||||
|
|
||||||
class AdminRadioSelect(forms.RadioSelect):
|
class AdminRadioSelect(forms.RadioSelect):
|
||||||
renderer = AdminRadioFieldRenderer
|
renderer = AdminRadioFieldRenderer
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms.util import flatatt
|
from django.forms.util import flatatt
|
||||||
from django.template import loader
|
from django.template import loader
|
||||||
|
from django.utils.html import format_html, format_html_join
|
||||||
from django.utils.http import int_to_base36
|
from django.utils.http import int_to_base36
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils.translation import ugettext, ugettext_lazy as _
|
from django.utils.translation import ugettext, ugettext_lazy as _
|
||||||
|
@ -28,13 +29,15 @@ class ReadOnlyPasswordHashWidget(forms.Widget):
|
||||||
try:
|
try:
|
||||||
hasher = identify_hasher(encoded)
|
hasher = identify_hasher(encoded)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
summary = "<strong>Invalid password format or unknown hashing algorithm.</strong>"
|
summary = mark_safe("<strong>Invalid password format or unknown hashing algorithm.</strong>")
|
||||||
else:
|
else:
|
||||||
summary = ""
|
summary = format_html_join('',
|
||||||
for key, value in hasher.safe_summary(encoded).iteritems():
|
"<strong>{0}</strong>: {1} ",
|
||||||
summary += "<strong>%(key)s</strong>: %(value)s " % {"key": ugettext(key), "value": value}
|
((ugettext(key), value)
|
||||||
|
for key, value in hasher.safe_summary(encoded).items())
|
||||||
|
)
|
||||||
|
|
||||||
return mark_safe("<div%(attrs)s>%(summary)s</div>" % {"attrs": flatatt(final_attrs), "summary": summary})
|
return format_html("<div{0}>{1}</div>", flatatt(final_attrs), summary)
|
||||||
|
|
||||||
|
|
||||||
class ReadOnlyPasswordHashField(forms.Field):
|
class ReadOnlyPasswordHashField(forms.Field):
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.db import models
|
||||||
from django.contrib.databrowse.datastructures import EasyModel
|
from django.contrib.databrowse.datastructures import EasyModel
|
||||||
from django.contrib.databrowse.sites import DatabrowsePlugin
|
from django.contrib.databrowse.sites import DatabrowsePlugin
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
|
from django.utils.html import format_html, format_html_join
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.encoding import force_unicode
|
from django.utils.encoding import force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -64,8 +65,9 @@ class CalendarPlugin(DatabrowsePlugin):
|
||||||
fields = self.field_dict(model)
|
fields = self.field_dict(model)
|
||||||
if not fields:
|
if not fields:
|
||||||
return ''
|
return ''
|
||||||
return mark_safe('<p class="filter"><strong>View calendar by:</strong> %s</p>' % \
|
return format_html('<p class="filter"><strong>View calendar by:</strong> {0}</p>',
|
||||||
', '.join(['<a href="calendars/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()]))
|
format_html_join(', ', '<a href="calendars/{0}/">{1}</a>',
|
||||||
|
((f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values())))
|
||||||
|
|
||||||
def urls(self, plugin_name, easy_instance_field):
|
def urls(self, plugin_name, easy_instance_field):
|
||||||
if isinstance(easy_instance_field.field, models.DateField):
|
if isinstance(easy_instance_field.field, models.DateField):
|
||||||
|
|
|
@ -5,6 +5,7 @@ from django.db import models
|
||||||
from django.contrib.databrowse.datastructures import EasyModel
|
from django.contrib.databrowse.datastructures import EasyModel
|
||||||
from django.contrib.databrowse.sites import DatabrowsePlugin
|
from django.contrib.databrowse.sites import DatabrowsePlugin
|
||||||
from django.shortcuts import render_to_response
|
from django.shortcuts import render_to_response
|
||||||
|
from django.utils.html import format_html, format_html_join
|
||||||
from django.utils.text import capfirst
|
from django.utils.text import capfirst
|
||||||
from django.utils.encoding import smart_str, force_unicode
|
from django.utils.encoding import smart_str, force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -32,8 +33,9 @@ class FieldChoicePlugin(DatabrowsePlugin):
|
||||||
fields = self.field_dict(model)
|
fields = self.field_dict(model)
|
||||||
if not fields:
|
if not fields:
|
||||||
return ''
|
return ''
|
||||||
return mark_safe('<p class="filter"><strong>View by:</strong> %s</p>' % \
|
return format_html('<p class="filter"><strong>View by:</strong> {0}</p>',
|
||||||
', '.join(['<a href="fields/%s/">%s</a>' % (f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values()]))
|
format_html_join(', ', '<a href="fields/{0}/">{1}</a>',
|
||||||
|
((f.name, force_unicode(capfirst(f.verbose_name))) for f in fields.values())))
|
||||||
|
|
||||||
def urls(self, plugin_name, easy_instance_field):
|
def urls(self, plugin_name, easy_instance_field):
|
||||||
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
|
if easy_instance_field.field in self.field_dict(easy_instance_field.model.model).values():
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker
|
from django.contrib.gis.maps.google.overlays import GPolygon, GPolyline, GMarker
|
||||||
|
@ -111,17 +112,18 @@ class GoogleMap(object):
|
||||||
@property
|
@property
|
||||||
def body(self):
|
def body(self):
|
||||||
"Returns HTML body tag for loading and unloading Google Maps javascript."
|
"Returns HTML body tag for loading and unloading Google Maps javascript."
|
||||||
return mark_safe('<body %s %s>' % (self.onload, self.onunload))
|
return format_html('<body {0} {1}>', self.onload, self.onunload)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def onload(self):
|
def onload(self):
|
||||||
"Returns the `onload` HTML <body> attribute."
|
"Returns the `onload` HTML <body> attribute."
|
||||||
return mark_safe('onload="%s.%s_load()"' % (self.js_module, self.dom_id))
|
return format_html('onload="{0}.{1}_load()"', self.js_module, self.dom_id)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def api_script(self):
|
def api_script(self):
|
||||||
"Returns the <script> tag for the Google Maps API javascript."
|
"Returns the <script> tag for the Google Maps API javascript."
|
||||||
return mark_safe('<script src="%s%s" type="text/javascript"></script>' % (self.api_url, self.key))
|
return format_html('<script src="{0}{1}" type="text/javascript"></script>',
|
||||||
|
self.api_url, self.key)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def js(self):
|
def js(self):
|
||||||
|
@ -131,17 +133,17 @@ class GoogleMap(object):
|
||||||
@property
|
@property
|
||||||
def scripts(self):
|
def scripts(self):
|
||||||
"Returns all <script></script> tags required with Google Maps JavaScript."
|
"Returns all <script></script> tags required with Google Maps JavaScript."
|
||||||
return mark_safe('%s\n <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n </script>' % (self.api_script, self.js))
|
return format_html('%s\n <script type="text/javascript">\n//<![CDATA[\n%s//]]>\n </script>', self.api_script, mark_safe(self.js))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def style(self):
|
def style(self):
|
||||||
"Returns additional CSS styling needed for Google Maps on IE."
|
"Returns additional CSS styling needed for Google Maps on IE."
|
||||||
return mark_safe('<style type="text/css">%s</style>' % self.vml_css)
|
return format_html('<style type="text/css">{0}</style>', self.vml_css)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def xhtml(self):
|
def xhtml(self):
|
||||||
"Returns XHTML information needed for IE VML overlays."
|
"Returns XHTML information needed for IE VML overlays."
|
||||||
return mark_safe('<html xmlns="http://www.w3.org/1999/xhtml" %s>' % self.xmlns)
|
return format_html('<html xmlns="http://www.w3.org/1999/xhtml" {0}>', self.xmlns)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def icons(self):
|
def icons(self):
|
||||||
|
|
|
@ -11,7 +11,7 @@ from django.forms.fields import Field, FileField
|
||||||
from django.forms.util import flatatt, ErrorDict, ErrorList
|
from django.forms.util import flatatt, ErrorDict, ErrorList
|
||||||
from django.forms.widgets import Media, media_property, TextInput, Textarea
|
from django.forms.widgets import Media, media_property, TextInput, Textarea
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
from django.utils.html import conditional_escape
|
from django.utils.html import conditional_escape, format_html
|
||||||
from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
|
from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
|
||||||
|
@ -167,7 +167,7 @@ class BaseForm(StrAndUnicode):
|
||||||
# punctuation.
|
# punctuation.
|
||||||
if self.label_suffix:
|
if self.label_suffix:
|
||||||
if label[-1] not in ':?.!':
|
if label[-1] not in ':?.!':
|
||||||
label += self.label_suffix
|
label = format_html('{}{}', label, self.label_suffix)
|
||||||
label = bf.label_tag(label) or ''
|
label = bf.label_tag(label) or ''
|
||||||
else:
|
else:
|
||||||
label = ''
|
label = ''
|
||||||
|
@ -498,8 +498,8 @@ class BoundField(StrAndUnicode):
|
||||||
def label_tag(self, contents=None, attrs=None):
|
def label_tag(self, contents=None, attrs=None):
|
||||||
"""
|
"""
|
||||||
Wraps the given contents in a <label>, if the field has an ID attribute.
|
Wraps the given contents in a <label>, if the field has an ID attribute.
|
||||||
Does not HTML-escape the contents. If contents aren't given, uses the
|
contents should be 'mark_safe'd to avoid HTML escaping. If contents
|
||||||
field's HTML-escaped label.
|
aren't given, uses the field's HTML-escaped label.
|
||||||
|
|
||||||
If attrs are given, they're used as HTML attributes on the <label> tag.
|
If attrs are given, they're used as HTML attributes on the <label> tag.
|
||||||
"""
|
"""
|
||||||
|
@ -508,7 +508,9 @@ class BoundField(StrAndUnicode):
|
||||||
id_ = widget.attrs.get('id') or self.auto_id
|
id_ = widget.attrs.get('id') or self.auto_id
|
||||||
if id_:
|
if id_:
|
||||||
attrs = attrs and flatatt(attrs) or ''
|
attrs = attrs and flatatt(attrs) or ''
|
||||||
contents = '<label for="%s"%s>%s</label>' % (widget.id_for_label(id_), attrs, unicode(contents))
|
contents = format_html('<label for="{0}"{1}>{2}</label>',
|
||||||
|
widget.id_for_label(id_), attrs, contents
|
||||||
|
)
|
||||||
return mark_safe(contents)
|
return mark_safe(contents)
|
||||||
|
|
||||||
def css_classes(self, extra_classes=None):
|
def css_classes(self, extra_classes=None):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils.html import conditional_escape
|
from django.utils.html import format_html, format_html_join
|
||||||
from django.utils.encoding import StrAndUnicode, force_unicode
|
from django.utils.encoding import StrAndUnicode, force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
@ -17,8 +17,10 @@ def flatatt(attrs):
|
||||||
The returned string will contain a leading space followed by key="value",
|
The returned string will contain a leading space followed by key="value",
|
||||||
XML-style pairs. It is assumed that the keys do not need to be XML-escaped.
|
XML-style pairs. It is assumed that the keys do not need to be XML-escaped.
|
||||||
If the passed dictionary is empty, then return an empty string.
|
If the passed dictionary is empty, then return an empty string.
|
||||||
|
|
||||||
|
The result is passed through 'mark_safe'.
|
||||||
"""
|
"""
|
||||||
return ''.join([' %s="%s"' % (k, conditional_escape(v)) for k, v in attrs.items()])
|
return format_html_join('', ' {}="{}"', attrs.items())
|
||||||
|
|
||||||
class ErrorDict(dict, StrAndUnicode):
|
class ErrorDict(dict, StrAndUnicode):
|
||||||
"""
|
"""
|
||||||
|
@ -31,9 +33,11 @@ class ErrorDict(dict, StrAndUnicode):
|
||||||
|
|
||||||
def as_ul(self):
|
def as_ul(self):
|
||||||
if not self: return ''
|
if not self: return ''
|
||||||
return mark_safe('<ul class="errorlist">%s</ul>'
|
return format_html('<ul class="errorlist">{}</ul>',
|
||||||
% ''.join(['<li>%s%s</li>' % (k, conditional_escape(force_unicode(v)))
|
format_html_join('', '<li>{0}{1}</li>',
|
||||||
for k, v in self.items()]))
|
((k, force_unicode(v))
|
||||||
|
for k, v in self.items())
|
||||||
|
))
|
||||||
|
|
||||||
def as_text(self):
|
def as_text(self):
|
||||||
return '\n'.join(['* %s\n%s' % (k, '\n'.join([' * %s' % force_unicode(i) for i in v])) for k, v in self.items()])
|
return '\n'.join(['* %s\n%s' % (k, '\n'.join([' * %s' % force_unicode(i) for i in v])) for k, v in self.items()])
|
||||||
|
@ -47,8 +51,11 @@ class ErrorList(list, StrAndUnicode):
|
||||||
|
|
||||||
def as_ul(self):
|
def as_ul(self):
|
||||||
if not self: return ''
|
if not self: return ''
|
||||||
return mark_safe('<ul class="errorlist">%s</ul>'
|
return format_html('<ul class="errorlist">{}</ul>',
|
||||||
% ''.join(['<li>%s</li>' % conditional_escape(force_unicode(e)) for e in self]))
|
format_html_join('', '<li>{}</li>',
|
||||||
|
((force_unicode(e),) for e in self)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def as_text(self):
|
def as_text(self):
|
||||||
if not self: return ''
|
if not self: return ''
|
||||||
|
|
|
@ -12,7 +12,7 @@ from urlparse import urljoin
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.forms.util import flatatt, to_current_timezone
|
from django.forms.util import flatatt, to_current_timezone
|
||||||
from django.utils.datastructures import MultiValueDict, MergeDict
|
from django.utils.datastructures import MultiValueDict, MergeDict
|
||||||
from django.utils.html import escape, conditional_escape
|
from django.utils.html import conditional_escape, format_html, format_html_join
|
||||||
from django.utils.translation import ugettext, ugettext_lazy
|
from django.utils.translation import ugettext, ugettext_lazy
|
||||||
from django.utils.encoding import StrAndUnicode, force_unicode
|
from django.utils.encoding import StrAndUnicode, force_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
@ -53,7 +53,7 @@ class Media(StrAndUnicode):
|
||||||
return mark_safe('\n'.join(chain(*[getattr(self, 'render_' + name)() for name in MEDIA_TYPES])))
|
return mark_safe('\n'.join(chain(*[getattr(self, 'render_' + name)() for name in MEDIA_TYPES])))
|
||||||
|
|
||||||
def render_js(self):
|
def render_js(self):
|
||||||
return ['<script type="text/javascript" src="%s"></script>' % self.absolute_path(path) for path in self._js]
|
return [format_html('<script type="text/javascript" src="{0}"></script>', self.absolute_path(path)) for path in self._js]
|
||||||
|
|
||||||
def render_css(self):
|
def render_css(self):
|
||||||
# To keep rendering order consistent, we can't just iterate over items().
|
# To keep rendering order consistent, we can't just iterate over items().
|
||||||
|
@ -61,7 +61,7 @@ class Media(StrAndUnicode):
|
||||||
media = self._css.keys()
|
media = self._css.keys()
|
||||||
media.sort()
|
media.sort()
|
||||||
return chain(*[
|
return chain(*[
|
||||||
['<link href="%s" type="text/css" media="%s" rel="stylesheet" />' % (self.absolute_path(path), medium)
|
[format_html('<link href="{0}" type="text/css" media="{1}" rel="stylesheet" />', self.absolute_path(path), medium)
|
||||||
for path in self._css[medium]]
|
for path in self._css[medium]]
|
||||||
for medium in media])
|
for medium in media])
|
||||||
|
|
||||||
|
@ -254,7 +254,7 @@ class Input(Widget):
|
||||||
if value != '':
|
if value != '':
|
||||||
# Only add the 'value' attribute if a value is non-empty.
|
# Only add the 'value' attribute if a value is non-empty.
|
||||||
final_attrs['value'] = force_unicode(self._format_value(value))
|
final_attrs['value'] = force_unicode(self._format_value(value))
|
||||||
return mark_safe('<input%s />' % flatatt(final_attrs))
|
return format_html('<input{} />', flatatt(final_attrs))
|
||||||
|
|
||||||
class TextInput(Input):
|
class TextInput(Input):
|
||||||
input_type = 'text'
|
input_type = 'text'
|
||||||
|
@ -295,7 +295,7 @@ class MultipleHiddenInput(HiddenInput):
|
||||||
# An ID attribute was given. Add a numeric index as a suffix
|
# An ID attribute was given. Add a numeric index as a suffix
|
||||||
# so that the inputs don't all have the same ID attribute.
|
# so that the inputs don't all have the same ID attribute.
|
||||||
input_attrs['id'] = '%s_%s' % (id_, i)
|
input_attrs['id'] = '%s_%s' % (id_, i)
|
||||||
inputs.append('<input%s />' % flatatt(input_attrs))
|
inputs.append(format_html('<input{} />', flatatt(input_attrs)))
|
||||||
return mark_safe('\n'.join(inputs))
|
return mark_safe('\n'.join(inputs))
|
||||||
|
|
||||||
def value_from_datadict(self, data, files, name):
|
def value_from_datadict(self, data, files, name):
|
||||||
|
@ -355,9 +355,9 @@ class ClearableFileInput(FileInput):
|
||||||
|
|
||||||
if value and hasattr(value, "url"):
|
if value and hasattr(value, "url"):
|
||||||
template = self.template_with_initial
|
template = self.template_with_initial
|
||||||
substitutions['initial'] = ('<a href="%s">%s</a>'
|
substitutions['initial'] = format_html('<a href="{0}">{1}</a>',
|
||||||
% (escape(value.url),
|
value.url,
|
||||||
escape(force_unicode(value))))
|
force_unicode(value))
|
||||||
if not self.is_required:
|
if not self.is_required:
|
||||||
checkbox_name = self.clear_checkbox_name(name)
|
checkbox_name = self.clear_checkbox_name(name)
|
||||||
checkbox_id = self.clear_checkbox_id(checkbox_name)
|
checkbox_id = self.clear_checkbox_id(checkbox_name)
|
||||||
|
@ -392,8 +392,9 @@ class Textarea(Widget):
|
||||||
def render(self, name, value, attrs=None):
|
def render(self, name, value, attrs=None):
|
||||||
if value is None: value = ''
|
if value is None: value = ''
|
||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, name=name)
|
||||||
return mark_safe('<textarea%s>%s</textarea>' % (flatatt(final_attrs),
|
return format_html('<textarea{0}>{1}</textarea>',
|
||||||
conditional_escape(force_unicode(value))))
|
flatatt(final_attrs),
|
||||||
|
force_unicode(value))
|
||||||
|
|
||||||
class DateInput(Input):
|
class DateInput(Input):
|
||||||
input_type = 'text'
|
input_type = 'text'
|
||||||
|
@ -511,7 +512,7 @@ class CheckboxInput(Widget):
|
||||||
if not (value is True or value is False or value is None or value == ''):
|
if not (value is True or value is False or value is None or value == ''):
|
||||||
# Only add the 'value' attribute if a value is non-empty.
|
# Only add the 'value' attribute if a value is non-empty.
|
||||||
final_attrs['value'] = force_unicode(value)
|
final_attrs['value'] = force_unicode(value)
|
||||||
return mark_safe('<input%s />' % flatatt(final_attrs))
|
return format_html('<input{} />', flatatt(final_attrs))
|
||||||
|
|
||||||
def value_from_datadict(self, data, files, name):
|
def value_from_datadict(self, data, files, name):
|
||||||
if name not in data:
|
if name not in data:
|
||||||
|
@ -543,7 +544,7 @@ class Select(Widget):
|
||||||
def render(self, name, value, attrs=None, choices=()):
|
def render(self, name, value, attrs=None, choices=()):
|
||||||
if value is None: value = ''
|
if value is None: value = ''
|
||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, name=name)
|
||||||
output = ['<select%s>' % flatatt(final_attrs)]
|
output = [format_html('<select{}>', flatatt(final_attrs))]
|
||||||
options = self.render_options(choices, [value])
|
options = self.render_options(choices, [value])
|
||||||
if options:
|
if options:
|
||||||
output.append(options)
|
output.append(options)
|
||||||
|
@ -553,15 +554,16 @@ class Select(Widget):
|
||||||
def render_option(self, selected_choices, option_value, option_label):
|
def render_option(self, selected_choices, option_value, option_label):
|
||||||
option_value = force_unicode(option_value)
|
option_value = force_unicode(option_value)
|
||||||
if option_value in selected_choices:
|
if option_value in selected_choices:
|
||||||
selected_html = ' selected="selected"'
|
selected_html = mark_safe(' selected="selected"')
|
||||||
if not self.allow_multiple_selected:
|
if not self.allow_multiple_selected:
|
||||||
# Only allow for a single selection.
|
# Only allow for a single selection.
|
||||||
selected_choices.remove(option_value)
|
selected_choices.remove(option_value)
|
||||||
else:
|
else:
|
||||||
selected_html = ''
|
selected_html = ''
|
||||||
return '<option value="%s"%s>%s</option>' % (
|
return format_html('<option value="{0}"{1}>{2}</option>',
|
||||||
escape(option_value), selected_html,
|
option_value,
|
||||||
conditional_escape(force_unicode(option_label)))
|
selected_html,
|
||||||
|
force_unicode(option_label))
|
||||||
|
|
||||||
def render_options(self, choices, selected_choices):
|
def render_options(self, choices, selected_choices):
|
||||||
# Normalize to strings.
|
# Normalize to strings.
|
||||||
|
@ -569,7 +571,7 @@ class Select(Widget):
|
||||||
output = []
|
output = []
|
||||||
for option_value, option_label in chain(self.choices, choices):
|
for option_value, option_label in chain(self.choices, choices):
|
||||||
if isinstance(option_label, (list, tuple)):
|
if isinstance(option_label, (list, tuple)):
|
||||||
output.append('<optgroup label="%s">' % escape(force_unicode(option_value)))
|
output.append(format_html('<optgroup label="{0}">', force_unicode(option_value)))
|
||||||
for option in option_label:
|
for option in option_label:
|
||||||
output.append(self.render_option(selected_choices, *option))
|
output.append(self.render_option(selected_choices, *option))
|
||||||
output.append('</optgroup>')
|
output.append('</optgroup>')
|
||||||
|
@ -618,7 +620,7 @@ class SelectMultiple(Select):
|
||||||
def render(self, name, value, attrs=None, choices=()):
|
def render(self, name, value, attrs=None, choices=()):
|
||||||
if value is None: value = []
|
if value is None: value = []
|
||||||
final_attrs = self.build_attrs(attrs, name=name)
|
final_attrs = self.build_attrs(attrs, name=name)
|
||||||
output = ['<select multiple="multiple"%s>' % flatatt(final_attrs)]
|
output = [format_html('<select multiple="multiple"{}>', flatatt(final_attrs))]
|
||||||
options = self.render_options(choices, value)
|
options = self.render_options(choices, value)
|
||||||
if options:
|
if options:
|
||||||
output.append(options)
|
output.append(options)
|
||||||
|
@ -662,11 +664,11 @@ class RadioInput(SubWidget):
|
||||||
value = value or self.value
|
value = value or self.value
|
||||||
attrs = attrs or self.attrs
|
attrs = attrs or self.attrs
|
||||||
if 'id' in self.attrs:
|
if 'id' in self.attrs:
|
||||||
label_for = ' for="%s_%s"' % (self.attrs['id'], self.index)
|
label_for = format_html(' for="{0}_{1}"', self.attrs['id'], self.index)
|
||||||
else:
|
else:
|
||||||
label_for = ''
|
label_for = ''
|
||||||
choice_label = conditional_escape(force_unicode(self.choice_label))
|
choice_label = force_unicode(self.choice_label)
|
||||||
return mark_safe('<label%s>%s %s</label>' % (label_for, self.tag(), choice_label))
|
return format_html('<label{0}>{1} {2}</label>', label_for, self.tag(), choice_label)
|
||||||
|
|
||||||
def is_checked(self):
|
def is_checked(self):
|
||||||
return self.value == self.choice_value
|
return self.value == self.choice_value
|
||||||
|
@ -677,7 +679,7 @@ class RadioInput(SubWidget):
|
||||||
final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
|
final_attrs = dict(self.attrs, type='radio', name=self.name, value=self.choice_value)
|
||||||
if self.is_checked():
|
if self.is_checked():
|
||||||
final_attrs['checked'] = 'checked'
|
final_attrs['checked'] = 'checked'
|
||||||
return mark_safe('<input%s />' % flatatt(final_attrs))
|
return format_html('<input{} />', flatatt(final_attrs))
|
||||||
|
|
||||||
class RadioFieldRenderer(StrAndUnicode):
|
class RadioFieldRenderer(StrAndUnicode):
|
||||||
"""
|
"""
|
||||||
|
@ -701,8 +703,10 @@ class RadioFieldRenderer(StrAndUnicode):
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
"""Outputs a <ul> for this set of radio fields."""
|
"""Outputs a <ul> for this set of radio fields."""
|
||||||
return mark_safe('<ul>\n%s\n</ul>' % '\n'.join(['<li>%s</li>'
|
return format_html('<ul>\n{0}\n</ul>',
|
||||||
% force_unicode(w) for w in self]))
|
format_html_join('\n', '<li>{0}</li>',
|
||||||
|
[(force_unicode(w),) for w in self]
|
||||||
|
))
|
||||||
|
|
||||||
class RadioSelect(Select):
|
class RadioSelect(Select):
|
||||||
renderer = RadioFieldRenderer
|
renderer = RadioFieldRenderer
|
||||||
|
@ -751,15 +755,16 @@ class CheckboxSelectMultiple(SelectMultiple):
|
||||||
# so that the checkboxes don't all have the same ID attribute.
|
# so that the checkboxes don't all have the same ID attribute.
|
||||||
if has_id:
|
if has_id:
|
||||||
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
|
final_attrs = dict(final_attrs, id='%s_%s' % (attrs['id'], i))
|
||||||
label_for = ' for="%s"' % final_attrs['id']
|
label_for = format_html(' for="{0}"', final_attrs['id'])
|
||||||
else:
|
else:
|
||||||
label_for = ''
|
label_for = ''
|
||||||
|
|
||||||
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
|
cb = CheckboxInput(final_attrs, check_test=lambda value: value in str_values)
|
||||||
option_value = force_unicode(option_value)
|
option_value = force_unicode(option_value)
|
||||||
rendered_cb = cb.render(name, option_value)
|
rendered_cb = cb.render(name, option_value)
|
||||||
option_label = conditional_escape(force_unicode(option_label))
|
option_label = force_unicode(option_label)
|
||||||
output.append('<li><label%s>%s %s</label></li>' % (label_for, rendered_cb, option_label))
|
output.append(format_html('<li><label{0}>{1} {2}</label></li>',
|
||||||
|
label_for, rendered_cb, option_label))
|
||||||
output.append('</ul>')
|
output.append('</ul>')
|
||||||
return mark_safe('\n'.join(output))
|
return mark_safe('\n'.join(output))
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ from django.template.smartif import IfParser, Literal
|
||||||
from django.template.defaultfilters import date
|
from django.template.defaultfilters import date
|
||||||
from django.utils.encoding import smart_unicode
|
from django.utils.encoding import smart_unicode
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
from django.utils.html import format_html
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
|
||||||
register = Library()
|
register = Library()
|
||||||
|
@ -44,9 +45,9 @@ class CsrfTokenNode(Node):
|
||||||
csrf_token = context.get('csrf_token', None)
|
csrf_token = context.get('csrf_token', None)
|
||||||
if csrf_token:
|
if csrf_token:
|
||||||
if csrf_token == 'NOTPROVIDED':
|
if csrf_token == 'NOTPROVIDED':
|
||||||
return mark_safe("")
|
return format_html("")
|
||||||
else:
|
else:
|
||||||
return mark_safe("<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='%s' /></div>" % csrf_token)
|
return format_html("<div style='display:none'><input type='hidden' name='csrfmiddlewaretoken' value='{}' /></div>", csrf_token)
|
||||||
else:
|
else:
|
||||||
# It's very probable that the token is missing because of
|
# It's very probable that the token is missing because of
|
||||||
# misconfiguration, so we raise a warning
|
# misconfiguration, so we raise a warning
|
||||||
|
|
Loading…
Reference in New Issue