flask, matplotlib, HTML IMAGE

Django, Flask, Bottle, WSGI, CGI…
Antworten
telegraph
User
Beiträge: 31
Registriert: Mittwoch 6. November 2013, 10:59

Hallo zusammen,

wie bekomme ich das aus dem Plot ertsellten png in ein Bild auf der erstellten Seite?

Code: Alles auswählen

@app.route('/', methods=['POST', 'GET'])
def welcome():
    response = ""
    if 'username' in session:
        if request.method == 'POST':

            #values_of_interest = "Schaltkreis_1_Wirkenergie_kWh"
            values_of_interest = request.form.get('Plot_Daten')
            print(values_of_interest)

            conn = sqlite3.connect('C:\\Users\\teleg\\OneDrive\\Desktop\\Easy_projekt\\CSV_to_SQLite\\DB_egx300.db')
            c = conn.cursor()
            # Beschriftung = str(values_of_interest.replace('_', ' '))

            c.execute('SELECT {0}, Ortszeitstempel FROM egx300'.format(values_of_interest))
            dates = []
            values = []
            for row in c.fetchall():
                dates.append(row[1])
                values.append(row[0])
            #Erzeuge eine neu Figur

            fig = Figure(figsize=(20, 8))

            #Werte bilden
            summe = []
            x_zaeler = 0
            for i in dates:
                x_zaeler += 1

            print(x_zaeler)
            x_mid = x_zaeler / 2

            y_zaeler = 0

            for i in values:
                y_zaeler += 1
            y_mid = y_zaeler / 2

            #figur setup
            ax = fig.add_subplot(111)
            ax.set_xticks([1, x_mid, x_zaeler])
            ax.set_yticks([1, 10, 50, 100, 150, 200, 300])
            ax.set_title(values_of_interest)

            ax.plot(dates, values)
            ax.set_xticklabels(dates, rotation=0)

            #Figur Convertieren

            img = io.BytesIO()
            canvas = FigureCanvasAgg(fig)
            canvas.print_figure(img, format='png')
            response = make_response(img.getvalue())
            response.headers['Content-Type'] = 'image/png'
            print(type(response))



        return render_template('welcome.html', username=session['username'], response=response)
    else:
        return redirect(url_for('login'))
[codebox=html5 file=Unbenannt.html]
welcom.html
<div>
<form action="{{url_for('welcome')}}" method="POST" id="select2" name="Plot_Daten" >
<select name="Plot_Daten" size="14" >
<option value="Wirkenergie_kWh">Wirkengie</option>
<option value="Strommittelwert_L1">L1</option>
<option value="Strommittelwert_L2">L2</option>
<option value="Strommittelwert_L3">L3</option>
<option value="Schaltkreis_1_Wirkenergie_kWh">Wirkenergie 1</option>
<option value="Schaltkreis_1_Strommittelwert_A">Strommittelwert 1</option>
<option value="Schaltkreis_2_Wirkenergie_kWh">Wirkenergie 2</option>
<option value="Schaltkreis_2_Strommittelwert_A">Strommittelwert 2</option>
<option value="Schaltkreis_3_Wirkenergie_kWh">Wirkenergie 3</option>
<option value="Schaltkreis_3_Strommittelwert_A">Strommittelwert 3</option>
<option value="Schaltkreis_4_Wirkenergie_kWh">Wirkenergie 4</option>
<option value="Schaltkreis_4_Strommittelwert_A">Strommittelwert 4</option>

</select><br>
<input type="submit">

</form>
<p>
{{request.form.get('Plot_Daten')}} #work
{{response}} #type(<class 'flask.wrappers.Response'>) <Response 44257 bytes [200 OK]>
<img src="data:image/png;base64,{{ response }}" width="500">

{% if response != None %}
<img src="data:image/png;base64,{{ response }}" width="500"># ???
{% endif %}
</p>
<p>
<img src={{response}} alt="Loading Plot" />#???
</p>

</div>
[/code]
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@telegraph: die Funktion `welcome` ist zu lang, um sie zu verstehen; ich habe Dir glaube ich schon einmal geschrieben, dass man keine SQL-Befehle zusammenformatieren sollte, und vor allem NIEMALS Userinput ungeprüft in SQL-Befehle hineinformatieren DARF. `values_of_interest` könnte im Extremfall Befehle enthalten, die Dir Deine Festplatte formatieren. fetchall ist unnötig, da man direkt über den Cursor (dessen Name `c` zu kurz ist) iterieren kann. `row` entpackt man am Besten schon im for: `for value, date in c:`
Um die Länge einer Liste zu ermitteln, gibt es bessere Wege, als die Liste durchzugehen und jeweils 1 aufzuaddieren. `summe`, `y_zaeler` und `y_mid` werden nicht verwendet.

Du mischt hier zwei Dinge. Entweder Du lieferst eine HTML-Seite zurück, mit eingebettetem Bild (Bilddaten BASE64-codiert) oder Du lieferst eine HTML-Seite zurück, die eine URL enthält und schreibst zusätzlich noch eine Funktion, die das Bild über diese URL zurückliefert. In diesem Fall würde ich zweiteres empfehlen.

Da die Auswahl des Plots eine Abfrage ist, ist ein POST-Request das falsche. Den GET-Request auf welcome.html mit der Plot-Auswahl würde ich komplett durch Javascript ersetzen, das einfach nur die Quelle des Bildes anpasst.
[codebox=html5 file=Unbenannt.html]<div>
<select id="daten_select" size="14" onchange="var p=document.getElementById('plot_daten'); p.src=p.src.replace(/=.*?$/, '=' + document.getElementById('daten_select').value)">
<option value="Wirkenergie_kWh">Wirkengie</option>
<option value="Strommittelwert_L1">L1</option>
<option value="Strommittelwert_L2">L2</option>
<option value="Strommittelwert_L3">L3</option>
<option value="Schaltkreis_1_Wirkenergie_kWh">Wirkenergie 1</option>
<option value="Schaltkreis_1_Strommittelwert_A">Strommittelwert 1</option>
<option value="Schaltkreis_2_Wirkenergie_kWh">Wirkenergie 2</option>
<option value="Schaltkreis_2_Strommittelwert_A">Strommittelwert 2</option>
<option value="Schaltkreis_3_Wirkenergie_kWh">Wirkenergie 3</option>
<option value="Schaltkreis_3_Strommittelwert_A">Strommittelwert 3</option>
<option value="Schaltkreis_4_Wirkenergie_kWh">Wirkenergie 4</option>
<option value="Schaltkreis_4_Strommittelwert_A">Strommittelwert 4</option>
</select>
<img id="plot_daten" src="{{url_for('plot_daten')}}?plot=Wirkenergie_kWh" />
</div>[/code]
telegraph
User
Beiträge: 31
Registriert: Mittwoch 6. November 2013, 10:59

Hallo Sirius3,

leider bekomme ich mit beiden Methoden die Ausgabe des Bildes nicht hin, was zur Zeit das Primär Ziel ist. Leider verstehe ich nicht was ich noch brauche.
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@telegraph: welche beiden Methoden? Was hast Du konkret versucht? Was funktioniert bei der von mir vorgeschlagenen Methode nicht?
telegraph
User
Beiträge: 31
Registriert: Mittwoch 6. November 2013, 10:59

Das funktioniert so weit, allerdings wenn wenn noch keine werte gesetzt sind wird die Seite nicht aufgerufen da es noch keinen wert für .decode('utf8') gibt und die Bilder Vermischen sich nach mehr maligen ausführen! Den Fehler hab ich noch nicht gefunden.

Code: Alles auswählen

@app.route('/', methods=['POST', 'GET'])
def welcome():
    response = ""
    if 'username' in session:
        if request.method == 'POST':

            values_of_interest = "Wirkenergie_kWh"

            values_of_interest = request.form.get('Plot_Daten', "Wirkenergie_kWh")
            print(values_of_interest)

            # Datenbank abfrage
            conn = sqlite3.connect('C:\\Users\\teleg\\OneDrive\\Desktop\\Easy_projekt\\CSV_to_SQLite\\DB_egx300.db')
            c = conn.cursor()
            c.execute('SELECT {0}, Ortszeitstempel FROM egx300'.format(values_of_interest))

            #Daten aufbereiten
            dates = []
            values = []
            for row in c.fetchall():
                dates.append(row[1])
                values.append(row[0])



            img = io.BytesIO()


            # Erzeuge eine neu Figur
            plt.plot(dates, values)
            plt.title(values_of_interest)
            plt.yticks()
            plt.xticks()

            plt.savefig(img, format='png')
            #img.seek(1)
            
            response = base64.b64encode(img.getvalue())

            #if response != None:
                #response.decode('utf8')




        return render_template('welcome.html', username=session['username'], response=response.decode('utf8'))
    else:
        return redirect(url_for('login'))
[codebox=html5 file=Unbenannt.html]
<div class="row">
<div class="four columns">
<form action="{{url_for('welcome')}}" method="POST" id="select2" name="Plot_Daten" >
<select name="Plot_Daten" class="u-full-width" >
<option value="Wirkenergie_kWh">Wirkengie</option>
<option value="Strommittelwert_L1">L1</option>
<option value="Strommittelwert_L2">L2</option>
<option value="Strommittelwert_L3">L3</option>
<option value="Schaltkreis_1_Wirkenergie_kWh">Wirkenergie 1</option>
<option value="Schaltkreis_1_Strommittelwert_A">Strommittelwert 1</option>
<option value="Schaltkreis_2_Wirkenergie_kWh">Wirkenergie 2</option>
<option value="Schaltkreis_2_Strommittelwert_A">Strommittelwert 2</option>
<option value="Schaltkreis_3_Wirkenergie_kWh">Wirkenergie 3</option>
<option value="Schaltkreis_3_Strommittelwert_A">Strommittelwert 3</option>
<option value="Schaltkreis_4_Wirkenergie_kWh">Wirkenergie 4</option>
<option value="Schaltkreis_4_Strommittelwert_A">Strommittelwert 4</option>

</select><br>
<input class="button" type="submit">

</form>
</div>
<div class="eight columns">
<p>

{% if response != None %}
{{request.form.get('Plot_Daten')}}
<img src="data:image/png;base64,{{ response }}" width="500">
{% endif %}
</p>
</div>
</div>
</div>
[/code]
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@telegraph: Du hast ja auch alles ignoriert, was ich Dir vor ein paar Wochen zu Figures erzählt habe.
telegraph
User
Beiträge: 31
Registriert: Mittwoch 6. November 2013, 10:59

@Sirius3 , Das war nicht meine Absicht, wenn ich jetzt noch raus bekomme wieso der Plot alle Werte über nimmt, und ich das ding etwas ausgeräumt habe wird das noch mal probiert. Danke
Sirius3
User
Beiträge: 17710
Registriert: Sonntag 21. Oktober 2012, 17:20

@telegraph: Da gibt es nichts herauszubekommen, weil ich das Dein anfängliches Problem war und ich es Dir da schon geschrieben hatte.
Antworten