import xml.etree.ElementTree as ET from rest_framework import renderers class SubsonicJSONRenderer(renderers.JSONRenderer): def render(self, data, accepted_media_type=None, renderer_context=None): if not data: # when stream view is called, we don't have any data return super().render(data, accepted_media_type, renderer_context) final = { 'subsonic-response': { 'status': 'ok', 'version': '1.16.0', } } final['subsonic-response'].update(data) if 'error' in final: # an error was returned final['subsonic-response']['status'] = 'failed' return super().render(final, accepted_media_type, renderer_context) class SubsonicXMLRenderer(renderers.JSONRenderer): media_type = 'text/xml' def render(self, data, accepted_media_type=None, renderer_context=None): if not data: # when stream view is called, we don't have any data return super().render(data, accepted_media_type, renderer_context) final = { 'xmlns': 'http://subsonic.org/restapi', 'status': 'ok', 'version': '1.16.0', } final.update(data) if 'error' in final: # an error was returned final['status'] = 'failed' tree = dict_to_xml_tree('subsonic-response', final) return b'\n' + ET.tostring(tree, encoding='utf-8') def dict_to_xml_tree(root_tag, d, parent=None): root = ET.Element(root_tag) for key, value in d.items(): if isinstance(value, dict): root.append(dict_to_xml_tree(key, value, parent=root)) elif isinstance(value, list): for obj in value: root.append(dict_to_xml_tree(key, obj, parent=root)) else: root.set(key, str(value)) return root