Возникли проблемы с передачей аргументов декорированной функции в колбе

Я новичок в flask и python и создаю проект, который извлекает данные Twitter для выполнения анализа настроений по условиям поиска с использованием TextBlob для отображения некоторой визуальной статистики. Я сохранил некоторые статистические данные как переменные (процент положительных, отрицательных и нейтральных твитов) и пытаюсь передать их в функцию для создания круговой диаграммы. Эта функция оформлена так, что она передает полученный PNG-файл на HTML-страницу. Кажется, у меня проблемы с передачей этих переменных в мою функцию построения графика.

Вот часть моего анализа настроений:

def sentiment(userinput):
# creating object of TwitterClient Class
api = TwitterClient(userinput)
# calling function to get tweets
#searchterm = input("Enter query: ")
tweets = api.get_tweets(query=api.searchterm, count=10)

# picking positive tweets from tweets
ptweets = [tweet for tweet in tweets if tweet['sentiment'] == 'positive']
# percentage of positive tweets
ptweet_analyses_pie = 100 * len(ptweets) / len(tweets)

# picking negative tweets from tweets
ntweets = [tweet for tweet in tweets if tweet['sentiment'] == 'negative']
# percentage of negative tweets
ntweets_analyses_pie = (100 * len(ntweets) / len(tweets))

# percentage of neutral tweets
#leftoverTweets = tweets - ntweets - ptweets
nut_tweet_analyses_pie = (100 * (len(tweets) - len(ntweets) - len(ptweets)) / len(tweets))

pie_chart_img = pie_chart(ptweet_analyses_pie, nut_tweet_analyses_pie, ntweets_analyses_pie)

return ptweets, ntweets, ptweet_analyses, ntweets_analyses, nut_tweet_analyses, pie_chart_img

Вот где вызывается функцияentiment():

@app.route('/render_Data', methods = ['GET', 'POST'])
def render_Data():
    if request.method == 'POST':
        tweets=request.form['tweets']
        ptweets, ntweets, ptweet_analyses, ntweets_analyses, nut_tweet_analyses, pie_chart_img = sentiment(tweets)

    return render_template('render_Data.html', ptweets = ptweets, ntweets = ntweets, ptweet_analyses = ptweet_analyses,
ntweets_analyses = ntweets_analyses, nut_tweet_analyses = nut_tweet_analyses, pie_chart_img = pie_chart_img)

Здесь я создаю файл pie_chart.png и даю ему URL-адрес для отображения в формате html без сохранения в статике.

@app.route('/pie_chart.png')
def pie_chart(x,y,z):
    labels = 'Positive', 'Negative', 'Neutral'
    sizes = [x,y,z]
    colors = ['gold', 'pink', 'lightskyblue']
    explode = (0, 0, 0)  # explode 1st slice
    # Plot
    plt.axis('equal')
    plt.pie(sizes, explode=explode, labels=labels, colors=colors,
        autopct='%1.1f%%', shadow=True, startangle=140)
    img = BytesIO()
    plt.savefig(img)
    response = make_response(img.getvalue())
    response.mimetype = 'image/png'
    return response

И, наконец, HTML:

<img src='{{url_for('pie_chart')}}'>

К сожалению, я получаю сообщение об ошибке, когда пытаюсь отобразить результаты: в pie_chart() отсутствуют 3 обязательных позиционных аргумента: «x», «y» и «z».

Заранее спасибо! Я знаю, что мой код немного элементарный, так как я все еще нахожусь на начальной стадии кодирования, поэтому, пожалуйста, будьте помягче в своем ответе!


person EFryer    schedule 27.04.2018    source источник
comment
Просто подумайте, хотели бы вы использовать диаграммы Google для визуализации круговой диаграммы в своем шаблоне, я думаю, это может дать вам больше элегантности и гибкости. Если вы это сделаете, вам просто нужно передать цифры в свой шаблон, а затем js обрабатывает отображение диаграммы. Если вы это сделаете, я мог бы предоставить рабочий пример с вашим кодом выше.   -  person Moses N. Njenga    schedule 27.04.2018
comment
Спасибо за ответ Моисей! К сожалению, члены моей команды придерживаются matplotlib. Я не думал использовать диаграммы Google, но я потратил секунду, чтобы проверить их. Я согласен, что они кажутся чище и элегантнее. Я с нетерпением жду возможности поработать с ними над другими проектами.   -  person EFryer    schedule 30.04.2018


Ответы (1)


Вы очень близки к правильному решению! Маршрут над определением также должен содержать аргументы, необходимые для функции: @app.route('/piechart.png/<x>/<y>/<z>'), и вы также должны указать эти аргументы при вызове URL-адреса: <img src='{{url_for('pie_chart', x=1, y=2, z=3)}}'>

from flask import Flask, render_template_string, url_for, make_response
from io import BytesIO
import matplotlib
matplotlib.use('Agg')
from matplotlib import pyplot as plt

app = Flask(__name__)

@app.route('/piechart.png/<x>/<y>/<z>', methods=['GET', 'POST'])
def chart_maker(x, y, z):
    labels = 'Positive', 'Negative', 'Neutral'
    sizes = [x, y, z]
    colors = ['gold', 'pink', 'lightskyblue']
    explode = (0, 0, 0)
    plt.axis('equal')
    plt.pie(sizes, explode=explode, labels=labels, colors=colors,
            autopct='%1.1f%%', shadow=True, startangle=140)
    img = BytesIO()
    plt.savefig(img)
    response = make_response(img.getvalue())
    response.mimetype = 'image/png'
    return response

@app.route('/display_chart')
def display_chart():
    return render_template_string('<img src="{{url_for("chart_maker", x=1, y=2, z=3)}}">')

app.run() 

при посещении http://127.0.0.1:5000/display_chart возвращается: это изображение:

person Joost    schedule 27.04.2018