pythondjangomatplotlibsvgresize

Django - How can i resize the svg in the html template


I just created a matplot figure from a csv in django (line graph) and rendering it to the html template and I can't modify its dimensions

imgdata = io.StringIO()
        fig.savefig(imgdata, format='svg')
        imgdata.seek(0)
        data = imgdata.getvalue()
        return data
    data = isolate(selected_loc)
    return render(request, 'hello.html', {'data': data, 'locations' : list(locations)})


html template

<div class="figure" style="">{{ data|safe }}</div>

i tried styling the div in css

.figure {
        width: 40%;
        height: 500px;
      }

and it doesnt working only the div container expands but not the svg that just rendered

enter image description here


Solution

  • xml.etree.ElementTree is a python library that allows you to parse and manipulate svgs.

    Side note -> IDK what's happening with the 2 return statements, but I am going to assume I am ignorant as opposed to you being wrong, because presumably your svg is being shown.

    import xml.etree.ElementTree as ET
    from io import StringIO
    
    # this might've been the user defined function "isolate"
    # for the time being, this is my best guess
    def isolate(fig):
        # this will write the output of the figure into a string in an SVG format
        imgdata = io.StringIO()
        fig.savefig(imgdata, format='svg')
        imgdata.seek(0)
        data = imgdata.getvalue()
    
        # then you can do something like this to read the SVG into a tree
        # create a tree
        tree = ET.parse(data)
        # get the root
        root = tree.getroot()
    
        # whatever the namespace is typically "http://www.w3.org/2000/svg"
        # elements are the elements you are looking for
        for e in root.findall("{namespace}elements"):
            e.attrib["attribute_to_set"] = ""
    
        # set the "root" css values for height and width
        root.attrib["height"] = "100%"
        root.attrib["width"] = "100%"
    
        # tree.write() saves the file so you can write it to a BytesIO or StringIO
        imgdata = io.BytesIO()
        # the below should work.
        tree.write(imgdata)
        # then do more things with it
    
        return imgdata
        # this looks like it went into another function somewhere
    
    # also my best guess for what this function looked like
    def my_view(request):
        data = isolate(selected_loc)
        # some transform of data happened here to be able to send it
        # to the django template rendering system to be used
        return render(request, 'hello.html', {'data': data, 'locations' : list(locations)})
    

    Your css should also work, but I think you should be attaching it to the svg itself and not the container. There is a chance that some style is taking precedence over the style you're trying to apply, so you could always add an !important at the end of it, like so, border: solid black 1px !important; to rule that out.


    Given the information above, you have 2 options; Either use the CSS below or use the etree code and remove the svg {...} css I have below.

    If you don't have an id attached to the svg itself, you would have to select it:

    svg
    {
        width: 100%;
        /*height: 100%;*/
    }
    .container
    {
        width: 40%;
        height: 500px;
    }