Source code for oioioi.base.templatetags.simple_filters

import json
import types
from copy import copy

from django import template
from django.forms import CheckboxInput, CheckboxSelectMultiple, RadioSelect
from django.utils.html import escapejs
from django.utils.safestring import mark_safe

from oioioi.contests.scores import IntegerScore
from oioioi.pa.score import PAScore

[docs]register = template.Library()
@register.filter
[docs]def is_checkbox(field): return isinstance(field.field.widget, CheckboxInput)
@register.filter
[docs]def is_checkbox_select_multiple(field): return isinstance(field.field.widget, CheckboxSelectMultiple)
@register.filter
[docs]def is_radioselect(field): return isinstance(field.field.widget, RadioSelect)
@register.filter
[docs]def lookup(d, key): """ Lookup value from dictionary Example: {% load simple_filters %} {{ dict|lookup:key }} """ return d[key]
@register.filter
[docs]def safe_lookup(d, key): """ Lookup value from dictionary. Returns None if key ``key`` is not present in ``d``. Example: {% load simple_filters %} {{ dict|safe_lookup:key }} """ return d.get(key)
@register.filter
[docs]def multival_lookup(d, key): """ Returns a value list corresponding to a key from Django's MultiValueDict """ return d.getlist(key)
@register.filter(name='indent')
[docs]def indent_string(value, num_spaces=4): """ Adds ``num_spaces`` spaces at the beginning of every line in value. """ return ' ' * num_spaces + value.replace('\n', '\n' + ' ' * num_spaces)
[docs]def _append_attr(field, attribute, value): # adapted from 'django-widget-tweaks' field = copy(field) # decorate field.as_widget method with updated attributes old_as_widget = field.as_widget def as_widget(self, widget=None, attrs=None, only_initial=False): widget = widget or self.field.widget attrs = attrs or {} custom_append_attr = getattr(widget, "append_attr", None) if not (custom_append_attr and custom_append_attr(attribute, value)): if attrs.get(attribute): attrs[attribute] += " " + value elif widget.attrs.get(attribute): attrs[attribute] = widget.attrs[attribute] + " " + value else: attrs[attribute] = value if attribute == "type": # change the Input type self.field.widget.input_type = value del attrs["type"] html = old_as_widget(widget, attrs, only_initial) self.as_widget = old_as_widget return html field.as_widget = types.MethodType(as_widget, field) return field
@register.filter(name='add_class')
[docs]def add_class(field, css_class): """ Adds css class to a django form field :param field: form field :param css_class: css class :return: field with added class Example usage # my_app/forms.py ```python class MyForm(Form): my_field = forms.CharField(max_length=100) # my_app/views.py ```python def get_form(request): my_form = MyForm() return render(request, 'my_form.html', { form: my_form }) ``` # my_app/templates/my_form.html ```html {{ form.field|add_class:"my-class" }} ``` would generate ```html <input class="my-class" id="my_field" name="my_field" /> ``` """ return _append_attr(field, "class", css_class)
@register.filter
[docs]def add_form(field, form_id): return _append_attr(field, "form", form_id)
@register.filter
[docs]def partition(thelist, n): """ From: http://djangosnippets.org/snippets/6/ Break a list into ``n`` pieces. If ``n`` is not a divisor of the length of the list, then first pieces are one element longer then the last ones. That is:: >>> l = range(10) >>> partition(l, 2) [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9]] >>> partition(l, 3) [[0, 1, 2, 3], [4, 5, 6], [7, 8, 9]] >>> partition(l, 4) [[0, 1, 2], [3, 4, 5], [6, 7], [8, 9]] >>> partition(l, 5) [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]] You can use the filter in the following way: {% load simple_filters %} {% for sublist in mylist|parition:"3" %} {% for item in sublist %} do something with {{ item }} {% endfor %} {% endfor %} """ try: n = int(n) thelist = list(thelist) except (ValueError, TypeError): return [thelist] p = len(thelist) // n num_longer = len(thelist) - p * n return [thelist[((p + 1) * i) : ((p + 1) * (i + 1))] for i in range(num_longer)] + [ thelist[(p * i + num_longer) : (p * (i + 1) + num_longer)] for i in range(num_longer, n) ]
@register.filter
[docs]def cyclic_lookup(thelist, index): return thelist[index % len(thelist)]
@register.filter(name='zip')
[docs]def zip_lists(a, b): return list(zip(a, b))
@register.filter
[docs]def jsonify(value): """ Be careful when using it directly in js! Code like that: <script> var x = {{ some_user_data|jsonify }}; </script> contains an XSS vulnerability. That's because browsers will interpret </script> tag inside js string. """ return mark_safe(json.dumps(value))
@register.filter
[docs]def json_parse(value): """ This is a correct way of embedding json inside js in an HTML template. """ return mark_safe('JSON.parse(\'%s\')' % escapejs(json.dumps(value)))
@register.filter
[docs]def latex_escape(x): r""" Escape string for generating LaTeX report. Usage: {{ malicious|latex_escape }} Remember: when generating LaTeX report, you should always check whether \write18 is disabled! http://www.texdev.net/2009/10/06/what-does-write18-mean/ """ res = str(x) # Braces + backslashes res = res.replace('\\', '\\textbackslash\\q{}') res = res.replace('{', '\\{') res = res.replace('}', '\\}') res = res.replace('\\q\\{\\}', '\\q{}') # then everything followed by empty space repls = [ ('#', '\\#'), ('$', '\\$'), ('%', '\\%'), ('_', '\\_'), ('<', '\\textless{}'), ('>', '\\textgreater{}'), ('&', '\\ampersand{}'), ('~', '\\textasciitilde{}'), ('^', '\\textasciicircum{}'), ('"', '\\doublequote{}'), ('\'', '\\singlequote{}'), ] for key, value in repls: res = res.replace(key, value) return res
@register.filter
[docs]def result_color_class(raw_score): if raw_score in [None, '']: return '' if callable(getattr(raw_score, 'to_int', None)): score = raw_score.to_int() else: score = int(raw_score) if isinstance(raw_score, IntegerScore): score_max_value = 100 elif isinstance(raw_score, PAScore): score_max_value = 10 else: # There should be a method to get maximum points for # contest, for now, support just above cases. return '' if score == 0: return 'submission--WA' score_color_threshold = 25 buckets_count = 4 points_per_bucket = score_max_value / float(buckets_count) # Round down to multiple of $score_color_threshold. bucket = int(score / points_per_bucket) * score_color_threshold return 'submission--OK{}'.format(bucket)