DemocracyClub / dc_django_utils

Shared helpers and utility functions for DC websites
MIT License
0 stars 2 forks source link

Add DSLinkWidget code to reduce code duplication #59

Open Bekabyx opened 1 year ago

Bekabyx commented 1 year ago

When it comes to filtering, we implement a class called DSLinkWidget which allows us to iterate over choices in the template layer. Currently, this is just implemented as and when we need it per-project, but it should be centralised in this dc_django_utils.

This code is currently used in WCIVF and YNR (probably some other projects too).

_YNR doesn't currently use dc_djangoutils so we won't be able to do the switcheroo there until we've got both of the projects integrated together

The DSLinkWidget code:

class DSLinkWidget(LinkWidget):
    """
    The LinkWidget doesn't allow iterating over choices in the template layer
    to change the HTML wrapping the widget.

    This breaks the way that Django *should* work, so we have to subclass
    and alter the HTML in Python :/

    https://github.com/carltongibson/django-filter/issues/880
    """

    def render(self, name, value, attrs=None, choices=(), renderer=None):
        if not hasattr(self, "data"):
            self.data = {}
        if value is None:
            value = ""
        self.build_attrs(self.attrs, extra_attrs=attrs)
        output = []
        options = self.render_options(choices, [value], name)
        if options:
            output.append(options)
        # output.append('</ul>')
        return mark_safe("\n".join(output))

    def render_option(self, name, selected_choices, option_value, option_label):
        option_value = force_str(option_value)
        if option_label == BLANK_CHOICE_DASH[0][1]:
            option_label = "All"
        data = self.data.copy()
        data[name] = option_value
        selected = data == self.data or option_value in selected_choices
        try:
            url = data.urlencode()
        except AttributeError:
            url = urlencode(data)
        return self.option_string() % {
            "attrs": selected and ' aria-current="true"' or "",
            "query_string": url,
            "label": force_str(option_label),
        }