Django-tables2 KeyError when field has {curly brackets}

By bayman

I have a model with Artist and Track class and when the title field of a Track has curly brackets, I get a KeyError Exception. (E.g. Track Title “Beat It {Freestyle}”). Looks like django_tables2 is passing my Track title field value to string.format(). How do I prevent that in django_tables2?

models.py

class Artist (models.Model):
    name = models.CharField(max_length=100)
    slug = AutoSlugField(populate_from='name', unique=True, editable=True, slugify=custom_slugify)
class Track (models.Model):
    artist = models.ForeignKey(Artist, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Artist")
    user = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True, on_delete=models.SET_NULL, verbose_name="Submitted by", default=1)
    title = models.CharField(max_length=100, verbose_name="Title")
    timestamp = models.DateTimeField(default=timezone.now)

tables.py

class TrackTable(tables.Table):
    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user', None)
        self.artistlink = kwargs.pop('artistlink', None)
        super(TrackTable, self).__init__(*args, **kwargs)
def render_artist(self, value):
    if self.artistlink == True:
        return format_html('<a href="/music/by/{}">{}</a>', value.slug, value)
    else:
        return value
def render_user(self, value):
    return format_html('<a href="/users/{}">{}</a>', value, value)
download = DownloadColumn(empty_values=(), orderable=False)
track_id = tables.CheckBoxColumn(accessor="pk",
                            attrs = {"th__input": {"id": "checkAll"}},
                            orderable=False)
class Meta:
    model = Track
    attrs = {"class": "table table-bordered table-condensed table-striped", "id": "track-table",}
    fields = ('track_id', 'artist', 'title', 'user', 'download')

views.py

def profile_detail(request, slug=None):
    alpha_list = ['0-9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
    playlist_list = Playlist.objects.filter(user=request.user.id)
    track_list = Track.objects.filter(artist__slug=slug)
    ltr = slug[0].upper()
    artist = get_object_or_404(Artist, slug=slug)
    table = TrackTable(track_list, user=request.user, artistlink=False)
    RequestConfig(request, paginate={"per_page": 15}).configure(table)
    context = {
        "playlist_list": playlist_list,
        "track_list": track_list,
        "table": table,
        "alpha_list": alpha_list,
        "artist": artist,
    }
    return render(request, "profile_detail.html", context)

profile_detail.html

<form method='POST' id="add-track-form" action='{% url "playlists:playlist_addtrack" %}'>{% csrf_token %}
...
        {% render_table table "django_tables2/bootstrap3.html" %}
...
</form>

bootstrap3.html

% load querystring from django_tables2 %}
{% load trans blocktrans from i18n %}
{% load bootstrap3 %}
{% if table.page %}
    <div class="table-responsive">
{% endif %}
{% block table %}
    <table{% if table.attrs %} {{ table.attrs.as_html }}{% endif %}>
        {% block table.thead %}
            <thead>
            <tr>
                {% for column in table.columns %}
                    {% if column.orderable %}
                        <th {{ column.attrs.th.as_html }}><a href="{% querystring table.prefixed_order_by_field=column.order_by_alias.next %}">{{ column.header }}</a></th>
                    {% else %}
                        <th {{ column.attrs.th.as_html }}>{{ column.header }}</th>
                    {% endif %}
                {% endfor %}
            </tr>
            </thead>
        {% endblock table.thead %}
        {% block table.tbody %}
            <tbody>
            {% for row in table.page.object_list|default:table.rows %} {# support pagination #}
                {% block table.tbody.row %}
                    <tr class="{% cycle "odd" "even" %}">
                        {% for column, cell in row.items %}
                            <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
                        {% endfor %}
                    </tr>
                {% endblock table.tbody.row %}
            {% empty %}
                {% if table.empty_text %}
                    {% block table.tbody.empty_text %}
                        <tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
                    {% endblock table.tbody.empty_text %}
                {% endif %}
            {% endfor %}
            </tbody>
        {% endblock table.tbody %}
        {% block table.tfoot %}
            <tfoot></tfoot>
        {% endblock table.tfoot %}
    </table>
    </div> <!-- table-responsive -->
{% endblock table %}

trackback:

Template error:
In template /Users/will/bpmdata/bpmdb/templates/django_tables2/bootstrap3.html, error at line 29
   Freestyle   19 :                     {% endif %}
   20 :                 {% endfor %}
   21 :             </tr>
   22 :             </thead>
   23 :         {% endblock table.thead %}
   24 :         {% block table.tbody %}
   25 :             <tbody>
   26 :             {% for row in table.page.object_list|default:table.rows %} {# support pagination #}
   27 :                 {% block table.tbody.row %}
   28 :                     <tr class="{% cycle "odd" "even" %}">
   29 :                          {% for column, cell in row.items %}
   30 :                             <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
   31 :                         {% endfor %}
   32 :                     </tr>
   33 :                 {% endblock table.tbody.row %}
   34 :             {% empty %}
   35 :                 {% if table.empty_text %}
   36 :                     {% block table.tbody.empty_text %}
   37 :                         <tr><td colspan="{{ table.columns|length }}">{{ table.empty_text }}</td></tr>
   38 :                     {% endblock table.tbody.empty_text %}
   39 :                 {% endif %}
Traceback:
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/core/handlers/exception.py" in inner
  41.             response = get_response(request)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/core/handlers/base.py" in _legacy_get_response
  249.             response = self._get_response(request)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  187.                 response = self.process_exception_by_middleware(e, request)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/core/handlers/base.py" in _get_response
  185.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/will/bpmdata/bpmdb/profiles/views.py" in profile_detail
  136.  return render(request, "profile_detail.html", context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/shortcuts.py" in render
  30.     content = loader.render_to_string(template_name, context, request, using=using)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/loader.py" in render_to_string
  68.     return template.render(context, request)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  207.                     return self._render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/loader_tags.py" in render
  177.             return compiled_parent._render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/loader_tags.py" in render
  72.                 result = block.nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/defaulttags.py" in render
  322.                 return nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django_tables2/templatetags/django_tables2.py" in render
  154.             return template.render(context.flatten())
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/backends/django.py" in render
  66.             return self.template.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  207.                     return self._render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in _render
  199.         return self.nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/loader_tags.py" in render
  63.                 result = self.nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/loader_tags.py" in render
  63.                 result = self.nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/defaulttags.py" in render
  216.                     nodelist.append(node.render_annotated(context))
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/loader_tags.py" in render
  63.                 result = self.nodelist.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render
  990.                 bit = node.render_annotated(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/base.py" in render_annotated
  957.             return self.render(context)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/template/defaulttags.py" in render
  172.                 values = list(values)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django_tables2/rows.py" in items
  229.             yield (column, self.get_cell(column.name))
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django_tables2/rows.py" in get_cell
  180.             default=self.table.columns[name].default
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django_tables2/rows.py" in _get_and_render_with
  155.         return render_func(bound_column, value)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django_tables2/rows.py" in _call_render
  189.             self._optional_cell_arguments(bound_column, value)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django_tables2/utils.py" in call_with_appropriate
  511.     return fn(**kwargs)
File "/Users/will/bpmdata/bpmdb/profiles/tables.py" in render
  42.           return format_html(referral_url, artist=artist1, title=record.title)
File "/Users/will/.virtualenvs/bpmdb/lib/python3.5/site-packages/django/utils/html.py" in format_html
  100.     return mark_safe(format_string.format(*args_safe, **kwargs_safe))
Exception Type: KeyError at /music/by/michael-jackson/
Exception Value: 'Freestyle'

Source: Stack Overflow

    

Share it with your friends!

    Fatal error: Uncaught Exception: 12: REST API is deprecated for versions v2.1 and higher (12) thrown in /home/content/19/9652219/html/wp-content/plugins/seo-facebook-comments/facebook/base_facebook.php on line 1273