def render(self, value, record, bound_column): if not self.links: raise NotImplementedError('Links not assigned.') if not isinstance(self.links, (list, tuple, dict)): raise NotImplementedError('Links must be an iterable.') links = [] for link in self.links: title = link['title'] url = link['url'] attrs = link['attrs'] if 'attrs' in link else None if 'args' in link: args = [ a.resolve(record) if isinstance(a, A) else a for a in link['args'] ] else: args = None attrs = AttributeDict( attrs if attrs is not None else self.attrs.get('a', {})) try: attrs['href'] = urlresolvers.reverse(url, args=args) except urlresolvers.NoReverseMatch: attrs['href'] = url links.append('<a {attrs}>{text}</a>'.format(attrs=attrs.as_html(), text=mark_safe(title))) return mark_safe(self.delimiter.join(links))
def render(self, record, value): attrs = AttributeDict(self.attrs.get("span", {})) classes = [c for c in attrs.get("class", "").split(" ") if c] exists = None storage = getattr(value, "storage", None) if storage: # we'll assume value is a `django.db.models.fields.files.FieldFile` if self.verify_exists: exists = storage.exists(value.name) else: if self.verify_exists and hasattr(value, "name"): # ignore negatives, perhaps the file has a name but it doesn't # represent a local path... better to stay neutral than give a # false negative. exists = os.path.exists(value.name) or exists if exists is not None: classes.append("exists" if exists else "missing") attrs["title"] = value.name attrs["class"] = " ".join(classes) return format_html( "<span {attrs}>{text}</span>", attrs=attrs.as_html(), text=self.text_value(record, value), )
def attrs(self): ''' Proxy to `.Column.attrs` but injects some values of our own. A ``th`` and ``td`` are guaranteed to be defined (irrespective of what's actually defined in the column attrs. This makes writing templates easier. ''' # Start with table's attrs; Only 'th' and 'td' attributes will be used attrs = dict(self._table.attrs) # Update attrs to prefer column's attrs rather than table's attrs.update(dict(self.column.attrs)) # we take the value for 'cell' as the basis for both the th and td attrs cell_attrs = attrs.get('cell', {}) # override with attrs defined specifically for th and td respectively. kwargs = {'table': self._table} attrs['th'] = computed_values(attrs.get('th', cell_attrs), **kwargs) attrs['td'] = computed_values(attrs.get('td', cell_attrs), **kwargs) # wrap in AttributeDict attrs['th'] = AttributeDict(attrs['th']) attrs['td'] = AttributeDict(attrs['td']) # Override/add classes attrs['th']['class'] = self.get_th_class(attrs['th']) attrs['td']['class'] = self.get_td_class(attrs['td']) return attrs
def render(self, record, value): storage = getattr(value, 'storage', None) exists = None url = None if storage: # we'll assume value is a `django.db.models.fields.files.FieldFile` if self.verify_exists: exists = storage.exists(value.name) url = storage.url(value.name) else: if self.verify_exists and hasattr(value, 'name'): # ignore negatives, perhaps the file has a name but it doesn't # represent a local path... better to stay neutral than give a # false negative. exists = os.path.exists(value.name) or exists tag = 'a' if url else 'span' attrs = AttributeDict(self.attrs.get(tag, {})) attrs['title'] = value.name classes = [c for c in attrs.get('class', '').split(' ') if c] if exists is not None: classes.append('exists' if exists else 'missing') attrs['class'] = ' '.join(classes) if url: return self.render_link(url, record=record, value=value, attrs=attrs) else: return format_html( '<span {attrs}>{text}</span>', attrs=attrs.as_html(), text=self.text_value(record, value) )
def attrs(self): """ Proxy to `.Column.attrs` but injects some values of our own. A ``th`` and ``td`` are guaranteed to be defined (irrespective of what's actually defined in the column attrs. This makes writing templates easier. """ # Work on a copy of the attrs object since we're tweaking stuff attrs = dict(self.column.attrs) # Find the relevant th attributes (fall back to cell if th isn't # explicitly specified). attrs["td"] = td = AttributeDict(attrs.get('td', attrs.get('cell', {}))) attrs["th"] = th = AttributeDict(attrs.get("th", attrs.get("cell", {}))) # make set of existing classes. th_class = set((c for c in th.get("class", "").split(" ") if c)) # pylint: disable=C0103 td_class = set((c for c in td.get("class", "").split(" ") if c)) # pylint: disable=C0103 # add classes for ordering if self.orderable: th_class.add("orderable") th_class.add("sortable") # backwards compatible if self.is_ordered: th_class.add( "desc" if self.order_by_alias.is_descending else "asc") # Always add the column name as a class th_class.add(self.name) td_class.add(self.name) if th_class: th['class'] = " ".join(sorted(th_class)) if td_class: td['class'] = " ".join(sorted(td_class)) return attrs
def render(self, value, record, bound_column): if not self.links: raise NotImplementedError('Links not assigned.') if not isinstance(self.links, (list, tuple,dict)): raise NotImplementedError('Links must be an iterable.') links = [] for link in self.links: title = link['title'] url = link['url'] attrs = link['attrs'] if 'attrs' in link else None if 'args' in link: args = [a.resolve(record) if isinstance(a, A) else a for a in link['args']] else: args = None attrs = AttributeDict(attrs if attrs is not None else self.attrs.get('a', {})) try: attrs['href'] = urlresolvers.reverse(url, args=args) except urlresolvers.NoReverseMatch: attrs['href'] = url links.append('<a {attrs}>{text}</a>'.format( attrs=attrs.as_html(), text=mark_safe(title) )) return mark_safe(self.delimiter.join(links))
def render_attrs(attrs, **kwargs): ret = AttributeDict(kwargs) if attrs is not None: ret.update(attrs) return ret.as_html()
def attrs(self): """ Proxy to `.Column.attrs` but injects some values of our own. A ``th`` and ``td`` are guaranteed to be defined (irrespective of what's actually defined in the column attrs. This makes writing templates easier. """ # Work on a copy of the attrs object since we're tweaking stuff attrs = dict(self.column.attrs) # Find the relevant th attributes (fall back to cell if th isn't # explicitly specified). attrs['th'] = AttributeDict(attrs.get('th', attrs.get('cell', {}))) attrs['td'] = AttributeDict(attrs.get('td', attrs.get('cell', {}))) # make set of existing classes. th_class = set((c for c in attrs['th'].get('class', '').split(' ') if c)) td_class = set((c for c in attrs['td'].get('class', '').split(' ') if c)) # add classes for ordering if self.orderable: th_class.add('orderable') if self.is_ordered: th_class.add('desc' if self.order_by_alias.is_descending else 'asc') # Always add the column name as a class th_class.add(self.name) td_class.add(self.name) attrs['th']['class'] = ' '.join(sorted(th_class)) attrs['td']['class'] = ' '.join(sorted(td_class)) return attrs
def header(self): default = {"type": "checkbox", "class": "toggle-all", } general = self.attrs.get('input') specific = self.attrs.get('th__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s /> ' % attrs.as_html())
def render_link(self, uri, record, value, attrs=None): super(OpenColumn, self).render_link(uri, record, value, attrs) attrs = AttributeDict( attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri html = '<a {attrs}><span class="fa fa-{icon}"></span> {text}</a>'.format( attrs=attrs.as_html(), icon=self.icon, text='Open') return mark_safe(html)
def header(self): """Render the header cell.""" default = {"type": "checkbox"} general = self.attrs.get("input") specific = self.attrs.get("th__input") attrs = AttributeDict(default, **(specific or general or {})) return mark_safe("<label><input %s/><span></span></label>" % attrs.as_html()) # noqa
def header(self): if self.header_check: default = {'type': 'checkbox'} general = self.attrs.get('input') specific = self.attrs.get('th__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s/>' % attrs.as_html()) else: return super(CheckBoxColumn, self).header
def render(self, value, bound_column, record): default = {"type": "checkbox", "name": bound_column.name, "value": value} if self.is_checked(value, record): default.update({"checked": "checked"}) general = self.attrs.get("input") specific = self.attrs.get("td__input") attrs = AttributeDict(default, **(specific or general or {})) return mark_safe("<input %s/>" % attrs.as_html())
def render(self, value, bound_column): # pylint: disable=W0221 default = { 'type': 'text', 'name': bound_column.name, } general = self.attrs.get('input') specific = self.attrs.get('td__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s/>' % attrs.as_html())
def render_link(self, uri, value, attrs=None): attrs = AttributeDict(attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri return format_html( '<a {attrs}>{text}</a>', attrs=attrs.as_html(), text=value, )
def render(self, value, bound_column): default = { 'type': 'checkbox', 'name': bound_column.name, 'value': value } general = self.attrs.get('input') specific = self.attrs.get('td__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s/>' % attrs.as_html())
def render(self, value, bound_column): # pylint: disable=W0221 default = { 'type': 'checkbox', 'name': bound_column.name, 'value': value } general = self.attrs.get('input') specific = self.attrs.get('td__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<label><input %s/><span class="lbl"></span></label>' % attrs.as_html())
def render_link(self, uri, text, attrs=None): attrs = AttributeDict(attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri html = '<a {attrs}>{text}</a>'.format( attrs=attrs.as_html(), text=text.encode('utf-8') ) return mark_safe(html)
def render(self, value, record, bound_column): if self.action: url = crud_url(record, self.action) else: url = record.get_absolute_url() attrs = AttributeDict((("href", url),)) return format_html( "<a {attrs}>{text}</a>", attrs=attrs.as_html(), text=self.action_name, )
def header(self): default = { 'type': 'checkbox', 'class': "tableflat", 'id': "checkboxall", 'name': 'for_action', } general = self.attrs.get('input') specific = self.attrs.get('th__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s/>' % attrs.as_html())
def render(self, value, bound_column, record): default = {'type': 'radio', 'name': bound_column.name, 'value': value} if self.is_checked(value, record): default.update({ 'checked': 'checked', }) general = self.attrs.get('input') specific = self.attrs.get('td__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s/>' % attrs.as_html())
def render(self, value, record, bound_column): try: url = value.get_absolute_url() except (AttributeError, NoReverseMatch): return force_str(value) attrs = AttributeDict((("href", url),)) return format_html( "<a {attrs}>{text}</a>", attrs=attrs.as_html(), text=value, )
def render_link(self, uri, text, attrs=None): """ Render a hyperlink. :param uri: URI for the hyperlink :param text: value wrapped in ``<a></a>`` :param attrs: ``<a>`` tag attributes """ attrs = AttributeDict(attrs if attrs is not None else self.attrs.get("a", {})) attrs["href"] = uri html = "<a {attrs}>{text}</a>".format(attrs=attrs.as_html(), text=escape(text)) return mark_safe(html)
def attrs(self): ''' Proxy to `.Column.attrs` but injects some values of our own. A ``th``, ``td`` and ``tf`` are guaranteed to be defined (irrespective of what's actually defined in the column attrs. This makes writing templates easier. ``tf`` is not actually a HTML tag, but this key name will be used for attributes for column's footer, if the column has one. ''' # prepare kwargs for computed_values() kwargs = { 'table': self._table, 'bound_column': self, } # BoundRow.items() sets current_record and current_value when iterating over # the records in a table. if getattr(self, 'current_record', None) is not None and getattr( self, 'current_value', None) is not None: kwargs.update({ 'record': self.current_record, 'value': self.current_value }) # Start with table's attrs; Only 'th' and 'td' attributes will be used attrs = dict(self._table.attrs) # Update attrs to prefer column's attrs rather than table's attrs.update(dict(self.column.attrs)) # we take the value for 'cell' as the basis for both the th and td attrs cell_attrs = attrs.get('cell', {}) # override with attrs defined specifically for th and td respectively. attrs['th'] = computed_values(attrs.get('th', cell_attrs), kwargs=kwargs) attrs['td'] = computed_values(attrs.get('td', cell_attrs), kwargs=kwargs) attrs['tf'] = computed_values(attrs.get('tf', cell_attrs), kwargs=kwargs) # wrap in AttributeDict attrs['th'] = AttributeDict(attrs['th']) attrs['td'] = AttributeDict(attrs['td']) attrs['tf'] = AttributeDict(attrs['tf']) # Override/add classes attrs['th']['class'] = self.get_th_class(attrs['th']) attrs['td']['class'] = self.get_td_class(attrs['td']) attrs['tf']['class'] = self.get_td_class(attrs['tf']) return attrs
def render(self, value, bound_column, record): default = { "type": "checkbox", "name": bound_column.name, "value": value } if self.is_checked(value, record): default.update({"checked": "checked"}) general = self.attrs.get("input") specific = self.attrs.get("td__input") attrs = AttributeDict(default, **(specific or general or {})) return mark_safe("<input %s/>" % attrs.as_html())
def __init__(self, id, source=None, params=(), sortable=None, empty_text=None, attrs=None, template=None, data=None): """Initialize the table. Options that Table supports that affect the data presented are not supported in this subclass. Extra paramters are: :param id: The id of the table in the resulting HTML. You just need to provide something that will be unique in the generated page. :param source: The URL to get json data from. :param params: A tuple of arguments to pass to the get_queryset() method. :param data: The data to base the table on, if any. """ if data is not None: if source is not None or self.source is not None: raise AssertionError( "Do not specify both data and source when building a " "DataTablesTable") self.params = params data_backed_table = True else: data_backed_table = False data = [] if source is not None: self.source = source if template is None: template = 'ajax_table.html' # Even if this is an ajax backed table, we pass data here and patch # the queryset in below because of a bootstrapping issue: we want to # sort the initial queryset, and this is much cleaner if the table has # has its .columns set up which is only done in Table.__init__... super(DataTablesTable, self).__init__( data=data, sortable=sortable, empty_text=empty_text, attrs=attrs, template=template) self._full_length = None if not data_backed_table: self._compute_queryset(params) # We are careful about modifying the attrs here -- if it comes from # class Meta:-type options, we don't want to modify the original # value! if self.attrs: attrs = AttributeDict(self.attrs) else: attrs = AttributeDict() attrs.update({ 'id': id, # Forcing class to display here is a bit specific really. 'class': 'display', }) self.attrs = attrs
def render_link(self, uri, text, attrs=None): """ Render a hyperlink. :param uri: URI for the hyperlink :param text: value wrapped in ``<a></a>`` :param attrs: ``<a>`` tag attributes """ attrs = AttributeDict( attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri html = '<a {attrs}>{text}</a>'.format(attrs=attrs.as_html(), text=escape(text)) return mark_safe(html)
def render(self, value, bound_column, record): # pylint: disable=W0221 default = { 'type': 'checkbox', 'name': bound_column.name, 'value': value } if self.is_checked(value, record): default.update({ 'checked': 'checked', }) general = self.attrs.get('input') specific = self.attrs.get('td__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s/>' % attrs.as_html())
def render_link(self, uri, text, attrs=None): """ Render a hyperlink. :param uri: URI for the hyperlink :param text: value wrapped in ``<a></a>`` :param attrs: ``<a>`` tag attributes """ attrs = AttributeDict(attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri return format_html('<a {attrs}>{text}</a>', attrs=attrs.as_html(), text=text)
def test_render_attributes_test(self): template = Template('{% load django_tables2 %}{% render_attrs attrs class="table" %}') html = template.render(Context({})) self.assertEqual(html, 'class="table"') html = template.render(Context({"attrs": AttributeDict({"class": "table table-striped"})})) self.assertEqual(html, 'class="table table-striped"')
def render_link(self, uri, text, attrs=None, get_params_dict={}): """ Render a hyperlink. :param uri: URI for the hyperlink :param text: value wrapped in ``<a></a>`` :param attrs: ``<a>`` tag attributes """ attrs = AttributeDict(attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = "%s%s" % (uri, '' if not get_params_dict else '?'+"&".join( "%s=%s"%item for item in get_params_dict.items() )) html = '<a {attrs}>{text}</a>'.format( attrs=attrs.as_html(), text=escape(text) ) return mark_safe(html)
def render(self, value): value = bool(value) text = self.yesno[int(not value)] html = '<span %s>%s</span>' attrs = {"class": unicode(value).lower()} attrs.update(self.attrs.get("span", {})) return mark_safe(html % (AttributeDict(attrs).as_html(), escape(text)))
def render(self, value, record, bound_column): value = self._get_bool_value(record, value, bound_column) text = self.yesno[int(not value)] attrs = {'class': six.text_type(value).lower()} attrs.update(self.attrs.get('span', {})) return format_html('<span {}>{}</span>', AttributeDict(attrs).as_html(), escape(text))
def header(self): default = {'type': 'checkbox'} general = self.attrs.get('input') specific = self.attrs.get('th__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe( self.th__before_input) # +'<input %s/>' % attrs.as_html())
def test_handles_escaping(self): # django==3.0 replaces ' with ', drop first option if django==2.2 support is removed self.assertIn( AttributeDict({ "x": "\"'x&" }).as_html(), ('x=""'x&"', 'x=""'x&"'), )
def render_link(self, uri, record, value, attrs=None): ''' Render a hyperlink. Arguments: uri (str): URI for the hyperlink record: record currently being rendered value (str): value to be wrapped in ``<a></a>``, might be overridden by ``self.text`` attrs (dict): ``<a>`` tag attributes ''' attrs = AttributeDict( attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri return format_html('<a {attrs}>{text}</a>', attrs=attrs.as_html(), text=self.text_value(record, value))
def render_link(self, uri, record, value, attrs=None): """ Render a link (`<a>`). Arguments: uri (str): URI for the link record: record currently being rendered value (str): value to be wrapped in ``<a></a>``, might be overridden by ``self.text`` attrs (dict): ``<a>`` tag attributes """ attrs = AttributeDict( attrs if attrs is not None else self.attrs.get("a", {})) attrs["href"] = uri return format_html("<a {attrs}>{text}</a>", attrs=attrs.as_html(), text=self.text_value(record, value))
def render_link(self, uri, record, value, attrs=None): """ Render a hyperlink. :param uri: URI for the hyperlink :param record: record currently being rendered :param value: value wrapped in ``<a></a>``, might be overridden by ``self.text`` :param attrs: ``<a>`` tag attributes """ attrs = AttributeDict(attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri return format_html( '<a {attrs}>{text}</a>', attrs=attrs.as_html(), text=self.text_value(record, value) )
def attrs(self): """ Proxy to `.Column.attrs` but injects some values of our own. A ``th`` and ``td`` are guaranteed to be defined (irrespective of what's actually defined in the column attrs. This makes writing templates easier. """ # Start with table's attrs; Only 'th' and 'td' attributes will be used attrs = dict(self.table.attrs) # Update attrs to prefer column's attrs rather than table's attrs.update(dict(self.column.attrs)) # Column ordering class names ordering_class = attrs.get('th', {}).get('_ordering', {}) # Find the relevant th attributes (fall back to cell if th isn't # explicitly specified). attrs['th'] = AttributeDict(attrs.get('th', attrs.get('cell', {}))) attrs['td'] = AttributeDict(attrs.get('td', attrs.get('cell', {}))) # make set of existing classes. th_class = set( (c for c in attrs['th'].get('class', '').split(' ') if c)) td_class = set( (c for c in attrs['td'].get('class', '').split(' ') if c)) # add classes for ordering if self.orderable: th_class.add(ordering_class.get('orderable', 'orderable')) if self.is_ordered: th_class.add( ordering_class.get('descending', 'desc') if self.order_by_alias .is_descending else ordering_class.get('ascending', 'asc')) # Always add the column name as a class th_class.add(self.name) td_class.add(self.name) attrs['th']['class'] = ' '.join(sorted(th_class)) attrs['td']['class'] = ' '.join(sorted(td_class)) return attrs
def render_link(self, uri, record, value, attrs=None): ''' Render a hyperlink. Arguments: uri (str): URI for the hyperlink record: record currently being rendered value (str): value to be wrapped in ``<a></a>``, might be overridden by ``self.text`` attrs (dict): ``<a>`` tag attributes ''' attrs = AttributeDict(attrs if attrs is not None else self.attrs.get('a', {})) attrs['href'] = uri return format_html( '<a {attrs}>{text}</a>', attrs=attrs.as_html(), text=self.text_value(record, value) )
def render(self, value, record, bound_column): if not self.links: raise NotImplementedError("Links not assigned.") if not isinstance(self.links, (list, tuple, dict)): raise NotImplementedError("Links must be an iterable.") links = [] for link in self.links: title = link["title"] url = link["url"] urlme = None attrs = link["attrs"] if "attrs" in link else None if "args" in link: args = [a.resolve(record) if isinstance(a, A) else a for a in link["args"]] else: args = None if "url" in link and not isinstance(url, str): urlme = [a.resolve(record) if isinstance(a, A) else a for a in link["url"]][0] else: urlme = None attrs = AttributeDict(attrs if attrs is not None else self.attrs.get("a", {})) try: if isinstance(urlme, str): attrs["href"] = urlresolvers.reverse(urlme, args=args) else: attrs["href"] = urlresolvers.reverse(url, args=args) except urlresolvers.NoReverseMatch: if isinstance(urlme, str): attrs["href"] = urlme else: attrs["href"] = url links.append("<a {attrs}>{text}</a>".format(attrs=attrs.as_html(), text=mark_safe(title))) return mark_safe(self.delimiter.join(links))
def render(self, value): storage = getattr(value, "storage", None) exists = None url = None if storage: # we'll assume value is a `django.db.models.fields.files.FieldFile` if self.verify_exists: exists = storage.exists(value.name) url = storage.url(value.name) else: if self.verify_exists and hasattr(value, "name"): # ignore negatives, perhaps the file has a name but it doesn't # represent a local path... better to stay neutral than give a # false negative. exists = os.path.exists(value.name) or exists tag = 'a' if url else 'span' attrs = AttributeDict(self.attrs.get(tag, {})) attrs['title'] = value.name if url: attrs['href'] = url # add "exists" or "missing" to the class list classes = [c for c in attrs.get('class', '').split(' ') if c] if exists is True: classes.append("exists") elif exists is False: classes.append("missing") attrs['class'] = " ".join(classes) html = '<{tag} {attrs}>{text}</{tag}>'.format( tag=tag, attrs=attrs.as_html(), text=os.path.basename(value.name)) return mark_safe(html)
def header(self): default = {"type": "checkbox"} general = self.attrs.get("input") specific = self.attrs.get("th__input") attrs = AttributeDict(default, **(specific or general or {})) return mark_safe("<input %s/>" % attrs.as_html())
def header(self): default = {'type': 'checkbox'} general = self.attrs.get('input') specific = self.attrs.get('th__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<label><input name="checkall" %s/><span class="lbl"></span></label>' % attrs.as_html())
def header(self): default = {'type': 'checkbox'} general = self.attrs.get('input') specific = self.attrs.get('th__input') attrs = AttributeDict(default, **(specific or general or {})) return mark_safe('<input %s/>' % attrs.as_html())
def attribute_dict_handles_escaping(): x = AttributeDict({"x": '"\'x&'}) assert x.as_html() == 'x=""'x&"'
def test_handles_escaping(self): x = AttributeDict({'x': '"\'x&'}) self.assertEqual(x.as_html(), 'x=""'x&"')
def test_omits_None(self): x = AttributeDict({'x': None}) self.assertEqual(x.as_html(), '')