matplotlib in flask - Darstellung

Django, Flask, Bottle, WSGI, CGI…
Antworten
fine_then
User
Beiträge: 2
Registriert: Montag 3. Februar 2020, 19:27

Einen schönen Abend miteinander,

dies ist mein erster Beitrag in diesem Forum! Sollte meine Frage in diesem Abschnitt deplatziert sein, so bitte ich um Nachsicht und freue mich um jeden Hinweis, wo dieser besser aufgehoben sein könnte.
Zu meiner Frage:
Noch relativ neu im Bereich Python und Flask versuche ich aktuell ein von mir generiertes Diagramm (via Matplotlib) im Browser darzustellen...

Code: Alles auswählen

@app.route("/build_plot")
def build_plot():
    img = io.BytesIO()

    y = [1, 2, 3, 4, 5]
    x = [0, 2, 1, 3, 4]
    plt.plot(x, y)
    plt.grid()
    plt.xlabel('X-Achse')
    plt.ylabel('Y-Achse')
    plt.savefig(img, format='png')
    img.seek(0)

    plot_url = base64.b64encode(img.getvalue()).decode()

    return '<img src="data:image/png;base64,{}">'.format(plot_url)

Code: Alles auswählen

{% extends "layouts/main.html" %}

{% block content %}
    <img src="data:image/png;base64, {{ plot_url }}">
{% endblock %}
Das Diagramm selber wird auch korrekt (im Sinne der enthaltenen Daten) dargestellt, erscheint jedoch lediglich im oberen linken Bereich des Browsers. Der Layout-Abschnitt aus der 'main.html' wird ebenfalls
vollständig ignoriert.

Code: Alles auswählen

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <link rel="stylesheet" href="/static/lib/skeleton/normalize.css" />
    <link rel="stylesheet" href="/static/lib/skeleton/skeleton.css" />
    <link rel="stylesheet" href="/static/lib/style.css" />
</head>
<body>
    <div class="container">
        <ul class="navigation">
            <li class="navigation-item">
                <a href="/">Startseite</a>
            </li>
            <li class="navigation-item">
                <a href="/test">Testseite</a>
            </li>
            <li class="navigation-item">
                <a href="/currency">Wechselkurstabelle</a>
            </li>
            <li class="navigation-item">
                <a href="/build_plot">Build plot</a>
            </li>
        </ul>
        <div style="clear: both;">&nbsp;</div>

        {% block content %}{% endblock %}
    </div>
</body>
</html>
Was muss ich ändern bzw. ergänzen, damit die Darstellung innerhalb meines Browsers an das Layout angepasst wird. Oder aber gehe ich - was die Darstellung von Matplotlibgrafiken angeht - bereits
in die völlig falsche Richtung? Ich hoffe die Frage, wenn auch eher auf html innerhalb von Python und Flask bezogen, ist in diesem Bereich richtig aufgehoben und einigermaßen verständlich.

Vielen Dank und einen schönen Abend.
__deets__
User
Beiträge: 14545
Registriert: Mittwoch 14. Oktober 2015, 14:29

Ich persoenlich wuerde das nicht per matplotlib machen. Es gibt ja zB Bokeh, oder plotly, mit denen Diagramme gleich in HTML/SVG dargestellt werden. Die kannst du dann auch besser einbinden und skalieren.

Alternativ kannst du mit D3.js selbst etwas bauen, wenn du auf den Webserver wirklich angewiesen bist - was genau ist da das Ziel?
Sirius3
User
Beiträge: 18255
Registriert: Sonntag 21. Oktober 2012, 17:20

Du benutzt doch das Template in ›build_plot‹ gar nicht.
fine_then
User
Beiträge: 2
Registriert: Montag 3. Februar 2020, 19:27

@__deets__:
Im Grunde geht es mir um eine vernünftige Darstellung innerhalb des Browsers. Das Diagramm wird wie erwähnt zwar dargestellt, jedoch leider nur in einem Bruchteil des Browserfensters. Ich werde mir aber in jedem Fall einmal die von dir genannten Alternativen (bzw. besseren Lösungswege) anschauen. Danke dir für die schnelle Antwort.

@Sirius3:
Wie gesagt bin ich beim Thema HTML noch ziemlich frisch dabei, hatte im ersten Moment jedoch vermutet, dass ich irgendwo einen für andere grundsätzlichen bzw. offensichtlichen Fehler begehe. Worauf beziehst du dich mit "Du benutzt doch das Template in ›build_plot‹ gar nicht." denn genau?
Sirius3
User
Beiträge: 18255
Registriert: Sonntag 21. Oktober 2012, 17:20

Auf das `return`, das nur einen einfaches <img>-Tag liefert.
Antworten