pythonflasksvgbackend

Is there any solution that can show SVG without HTML tags using Flask?


Is there any solution that can show SVG without HTML tags using Flask?

I'm building project similar to this project,which allow user to show their current stats on their static website by generating image(in SVG) user's stats .

According to my understanding, the concept is:

  1. using GET parameters to specify user's data , theme, etc.
  2. the server query the user's data
  3. the server return an SVG with user's data

Example from the repository:
https://github-readme-streak-stats.herokuapp.com/?user=DenverCoder1

The result of the example:
https://i.sstatic.net/MvLwS.png

I wrote the back-end in Python with Flask.

However, I can't find a solution to show only SVG using Flask.

I have tried render_template() method or return raw string of SVG. Neither of them could show only SVG without HTML tag.

  1. using render_template()
@app.route("/test_rend" , methods=['GET'])
def Test_rend():
    ...
    
    return render_template("img.svg")
  1. return raw string of SVG
@app.route("/test_raw" , methods=['GET'])
def Test_raw():
    ...
    
    return '''
    <svg width="100px" height="100px" xmlns="http://www.w3.org/2000/svg">

        <rect height="100%" width="100%" fill="white" />

            <circle cx="50%" cy="45%" r="40%" fill-opacity="0" style="stroke:green; stroke-width:6%; " />

            <text x="20%" y="47%" fill="blue" font-size="1.3em" font-weight="bold">ZERO</text>

            <text x="26%" y="65%" fill="blue" font-size="1em" font-weight="900" >JUDGE</text>


            <line x1="5%" y1="10%" x2="95%" y2="10%" style="stroke:white; stroke-width:30%; "/>

            <line x1="5%" y1="20%" x2="95%" y2="20%" style="stroke:green; stroke-width:10%; "/>

            <line x1="5%" y1="25%" x2="95%" y2="25%" style="stroke:white; stroke-width:5%; "/>
    </svg>
    '''

The result of both code:
https://i.sstatic.net/EYr3V.png

Is there any solution that can show SVG without HTML tags using Flask?


Solution

  • In order to serve the data as a pure SVG file, it is necessary to define the mimetype of the response. The browser thus identifies the file using the 'Content-Type' header and interprets it correctly.

    This example shows the use of raw data.

    @app.route('/')
    def index():
        svg = '''
        <svg width="100px" height="100px" xmlns="http://www.w3.org/2000/svg">
            <rect height="100%" width="100%" fill="white" />
            <circle cx="50%" cy="45%" r="40%" fill-opacity="0" style="stroke:green; stroke-width:6%; " />
            <text x="20%" y="47%" fill="blue" font-size="1.3em" font-weight="bold">ZERO</text>
            <text x="26%" y="65%" fill="blue" font-size="1em" font-weight="900" >JUDGE</text>
            <line x1="5%" y1="10%" x2="95%" y2="10%" style="stroke:white; stroke-width:30%; "/>
            <line x1="5%" y1="20%" x2="95%" y2="20%" style="stroke:green; stroke-width:10%; "/>
            <line x1="5%" y1="25%" x2="95%" y2="25%" style="stroke:white; stroke-width:5%; "/>
        </svg>
        '''
        return app.response_class(svg, mimetype='image/svg+xml')
    

    Using render_template it would look like this.

    @app.route('/')
    def index():
        return app.response_class(
            render_template('img.svg'),
            mimetype='image/svg+xml'
        )