def _toggle_boolean(self, request):
        try:
            item_id = int(request.POST.get('item_id', None))
            attr = str(request.POST.get('attr', None))
        except:
            return HttpResponseBadRequest("Malformed request")

        if not request.user.is_staff:
            logger.warning(
                "Denied AJAX request by non-staff \"%s\" to toggle boolean"
                " %s for object #%s", request.user, attr, item_id)
            return HttpResponseForbidden(
                _("You do not have permission to modify this object"))

        self._collect_editable_booleans()

        if attr not in self._ajax_editable_booleans:
            return HttpResponseBadRequest("not a valid attribute %s" % attr)

        try:
            obj = self.model._default_manager.get(pk=item_id)
        except self.model.DoesNotExist:
            return HttpResponseNotFound("Object does not exist")

        if not self.has_change_permission(request, obj=obj):
            logger.warning(
                "Denied AJAX request by \"%s\" to toggle boolean %s for"
                " object %s", request.user, attr, item_id)
            return HttpResponseForbidden(
                _("You do not have permission to modify this object"))

        new_state = not getattr(obj, attr)
        logger.info(
            "Toggle %s on #%d %s to %s by \"%s\"",
            attr, obj.pk, obj, "on" if new_state else "off", request.user)

        try:
            before_data = self._ajax_editable_booleans[attr](self, obj)

            setattr(obj, attr, new_state)
            obj.save()

            # ???: Perhaps better a post_save signal?
            self._refresh_changelist_caches()

            # Construct html snippets to send back to client for status update
            data = self._ajax_editable_booleans[attr](self, obj)

        except Exception:
            logger.exception(
                "Unhandled exception while toggling %s on %s", attr, obj)
            return HttpResponseServerError(
                "Unable to toggle %s on %s" % (attr, obj))

        # Weed out unchanged cells to keep the updates small. This assumes
        # that the order a possible get_descendents() returns does not change
        # before and after toggling this attribute. Unlikely, but still...
        return HttpResponse(
            json.dumps([b for a, b in zip(before_data, data) if a != b]),
            content_type="application/json")
Handle an AJAX toggle_boolean request
dataset/ETHPy150Open feincms/feincms/feincms/admin/tree_editor.py/TreeEditor._toggle_boolean