I have a little flask application, it is mostly written with methods (just one class).
Can someone explain me - example would be great - why I am receiving 1 missing argument after adding self to method declaration?
Here is a code:
from __future__ import print_function
from flask import Flask, render_template, make_response
from flask import redirect, request, jsonify, url_for
from multiprocessing import Value
from flask_classful import FlaskView
#from settings import *
from utils.settings import *
import logging
import linecache
import os
import simplejson as json
import mysql.connector
counter = Value('i', 0)
app = Flask(__name__)
class FlaskCLS(FlaskView):
app.debug = False
app._static_folder = os.path.abspath("templates/static/")
#app.route('/v1/api/cords', methods=['GET', 'POST', 'OPTIONS'])
def snd_post():
res = make_response({'x': '55.333', 'y': '18.666'})
return res
#app.route('/', methods=['GET', 'POST', 'OPTIONS'])
def index():
result = []
data = request.data
with counter.get_lock():
counter.value += 1
out = counter.value
with open(str(out), 'a') as dumping:
json.dump(data, dumping)
# ----------------------parser-section------------
with open(str(out), 'r+') as file:
content = file.readlines()
for line in content:
result.append(line.replace('\\', "").replace('"', "").
replace('{', "").replace('}', '').
replace(']', '').replace(',','\n').
replace('[',''))
f = open(str(out), 'w')
f.write('')
f.close()
with open(str(out), 'a') as appending:
appending.write('')
for line in result:
appending.write(line)
# --------------------cords-grabbing-------------
x = linecache.getline(str(out), 1)
y = linecache.getline(str(out), 2)
fx = open('x', 'w')
fy = open('y', 'w')
fx.write(x)
fx.close()
fy.write(y)
fy.close()
mydb = mysql.connector.connect(
host=db_host,
user='root',
auth_plugin='mysql_native_password',
password=password,
buffered=buffered,
database=database)
mycursor = mydb.cursor()
mycursor.execute('select nazwa, x, y, SQRT(POW(69.1 * (x - 54.111), 2) + POW(69.1 *(18.222 - y)\
* COS(x / 57.3), 2)) as distance from wet_dane having distance <125 order by distance;')
mycursor.fetchall()
mydb.commit()
# ---------------------empty-files----------------
str_directory = '/var/www/html/'
list_files = [x for x in os.listdir(str_directory) if x[0] != '.']
for each_file in list_files:
file_path = '%s/%s' % (str_directory, each_file)
if os.path.getsize(file_path) == 0:
os.remove(file_path)
else:
pass
return render_template('layouts/index.html')
flask = FlaskCLS()
# ---------------------runner-section-------------
if __name__ == '__main__':
log = logging.getLogger('werkzeug')
log.disabled = True
app.run(host, port, debug, ssl_context=context)
My point is - how properly add self to index and snd_post methods?
I want to pass - for example - x variable from index to snd_post in the same class.
Without self flask doesn't allow me to do such an operation.
Thanks.
I don't have experience with Flask-Classful, but it looks that you are supposed to register the routes to the app this way:
class QuotesView(FlaskView):
def index(self):
return "Hello"
QuotesView.register(app)
Instead of the #app.route(...) decorator.
Ok, i've made a solution for this, now my main python file looks like this:
from __future__ import print_function
from flask import Flask, render_template, make_response
from multiprocessing import Value
from utils.settings import *
from py_methods.post import Post
from py_methods.db_connect import Db_conn
from py_methods.empty_files_del import DeleteEmpty
from py_methods.files_operations import Files
import logging
import os
app = Flask(__name__)
app.debug = False
app._static_folder = os.path.abspath("templates/static/")
#app.route('/v1/api/cords', methods=['GET', 'POST', 'OPTIONS'])
def snd_post():
return Post.snd_post()
class Main():
#app.route('/', methods=['GET', 'POST', 'OPTIONS'])
def index():
Files.parsing()
DeleteEmpty.del_empty()
Db_conn.wet_db()
return render_template('layouts/index.html')
# ---------------------runner-section-------------
if __name__ == '__main__':
log = logging.getLogger('werkzeug')
log.disabled = True
app.run(host, port, debug, ssl_context=context)
So it's just a runner - every method I wrote has own file and own class. This allow me to inheritance the variables. We can close this topic. Thansk for the answers.
Related
I want to build a Line chatbot that when a POST requests is received and will parse the receive POST requests information to the chatbot users.
import os
import sys
from argparse import ArgumentParser
import json
from flask import Flask, request, abort,Response,jsonify
import requests
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError, LineBotApiError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,SourceUser
)
app = Flask(__name__)
data=''
#app.route('/data', methods=['POST'])
def get_data():
"""devicename,exceptionType,temperature,mask,stranger"""
device_name = request.form.get('device_name')
exceptionType = request.form.get('exceptionType')
temperature = request.form.get('temperature')
mask = request.form.get('mask')
stranger = request.form.get('stranger')
global data
data=f"device_name = {device_name} exceptionType = {exceptionType} temperature = {temperature} mask = {mask} stranger = {stranger}"
return_status = {"success":"true"}
return jsonify(return_status)
while len(data) > 1:
try:
line_bot_api.broadcast(
messages=TextSendMessage(text=str(data))
)
data=''
except LineBotApiError as e:
raise e
if __name__ == "__main__":
arg_parser = ArgumentParser(
usage='Usage: python ' + __file__ + ' [--port <port>] [--help]'
)
arg_parser.add_argument('-p', '--port', default=8000, help='port')
arg_parser.add_argument('-d', '--debug', default=False, help='debug')
options = arg_parser.parse_args()
app.run(debug=options.debug, port=options.port)
here I have two parts, first is the POST requests receiver. and second is the part that checks the condition if data is present. But when I send the POST requests, the line_bot_api.broadcast does not send the message to the chatbot user. I only saw examples of flask code that has a #app.route() so I was wondering if something like this works? or is there a better way to implement the condition (instead of checking data value, is it better to check if function get_data() ran or requests has been sent to our /data route)
The while loop stops immediately because the condition fails. One way to get around this and do what you want is by using threads.
import os
import sys
from argparse import ArgumentParser
import json
import threading
from flask import Flask, request, abort,Response,jsonify
import requests
from linebot import (
LineBotApi, WebhookHandler
)
from linebot.exceptions import (
InvalidSignatureError, LineBotApiError
)
from linebot.models import (
MessageEvent, TextMessage, TextSendMessage,SourceUser
)
app = Flask(__name__)
data=''
#app.route('/data', methods=['POST'])
def get_data():
"""devicename,exceptionType,temperature,mask,stranger"""
device_name = request.form.get('device_name')
exceptionType = request.form.get('exceptionType')
temperature = request.form.get('temperature')
mask = request.form.get('mask')
stranger = request.form.get('stranger')
global data
data=f"device_name = {device_name} exceptionType = {exceptionType} temperature = {temperature} mask = {mask} stranger = {stranger}"
return_status = {"success":"true"}
return jsonify(return_status)
def broadcast():
while True:
if len(data) < 1 : continue
try:
line_bot_api.broadcast(
messages=TextSendMessage(text=str(data))
)
data=''
except LineBotApiError as e:
raise e
if __name__ == "__main__":
arg_parser = ArgumentParser(
usage='Usage: python ' + __file__ + ' [--port <port>] [--help]'
)
arg_parser.add_argument('-p', '--port', default=8000, help='port')
arg_parser.add_argument('-d', '--debug', default=False, help='debug')
options = arg_parser.parse_args()
broadcast_thread = threading.Thread(target=broadcast)
broadcast_thread.start()
app.run(debug=options.debug, port=options.port)
This is definitely not the best way. But it works.
i am starting with Python and while i was working on a project found this issue:
I have 2 .py files. One that has a Login and one that has a chart built with the Streamlit library.
The thing is that i want to redirect the user to the chart once he logs in. I havent found any response to this issue or i just dont get it.
What i think i have to do is wrap the Streamlit Graph file into a function but i dont know how.
Thanks for anyone reading this.
Login File:
from flask import Flask, render_template, redirect, url_for,request, session
from flask_mysql_connector import MySQL
import pymysql
from templates.home import get_input
app = Flask(__name__)
app.secret_key = "120395"
app.config["MYSQL_HOST"] = "localhost"
app.config["MYSQL_USER"] = "root"
app.config["MYSQL_PASSWORD"] = "anto1203"
app.config["MYSQL_DB"] = "amsterdamdb"
db = MySQL(app)
#app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
if ('email_usuario_form' in request.form) and ('password_usuario_form' in request.form):
usuarios_email_py = request.form['email_usuario_form']
usuarios_password_py = request.form['password_usuario_form']
cursor = db.connection.cursor(pymysql.cursors.DictCursor)
cursor.execute("SELECT USUARIOS_EMAIL, USUARIOS_LOGIN_PASSWORD FROM amsterdamdb.usuarios WHERE "
"USUARIOS_EMAIL=%s AND USUARIOS_LOGIN_PASSWORD=%s", (usuarios_email_py,
usuarios_password_py))
info = cursor.fetchone()
print(info)
if info is None:
return "Usuario y contraseña incorrectos"
else:
if info[0] == usuarios_email_py and info[1] == usuarios_password_py:
session['loginsuccess'] = True
return redirect(url_for("home"))
return render_template("login.html")
#app.route('/registro')
def registro():
return render_template("register.html")
#app.route('/home')
def home():
if session['loginsuccess'] == True:
return get_input()
if __name__ == '__main__':
app.run(debug=True)
Streamlit Graph File
import streamlit as st
import pandas as pd
from PIL import Image
from datetime import datetime, timedelta
import json
import requests
import altair as alt
st.write("""
# Bienvenido a Ámsterdam
**Mostrando información del mercado de acciones**
""")
st.sidebar.header('Ingrese parámetros')
def get_input():
aux_datetime = datetime.now()
today_date = aux_datetime.date()
treinta_dias_date = today_date - timedelta(days=30)
get_fecha_desde = st.sidebar.text_input("Fecha Inicial", treinta_dias_date )
get_fecha_hasta = st.sidebar.text_input("Fecha Final", today_date)
get_nemotecnico = st.sidebar.text_input("Identificador", "goog" )
return get_fecha_desde, get_fecha_hasta, get_nemotecnico
def get_data(nemotecnico_empresa, fecha_desde, fecha_hasta):
nemotecnico = nemotecnico_empresa
from_input_fecha_desde,from_input_fecha_hasta,from_input_nemotecnico = get_input()
fecha_desde = datetime.strptime(from_input_fecha_desde, '%Y-%m-%d')
fecha_hasta = datetime.strptime(from_input_fecha_hasta, '%Y-%m-%d')
nemotecnico = from_input_nemotecnico.upper()
fecha_desde_tmsp = str(round(datetime.timestamp(fecha_desde)))
fecha_hasta_tmsp = str(round(datetime.timestamp(fecha_hasta)))
if nemotecnico=="":
r = requests.get(
'https://finnhub.io/api/v1/stock/candle?symbol=&resolution=1&from=0&to=0&token=btagn3v48v6vivh8p9n0')
accionesJson = r.json()
else:
r = requests.get(
'https://finnhub.io/api/v1/stock/candle?symbol=' + nemotecnico + '&resolution=D&from=' + fecha_desde_tmsp + '&to=' + fecha_hasta_tmsp + '&token=wathever')
accionesJson = r.json()
open_values = accionesJson["o"]
close_values = accionesJson["c"]
fecha_values = accionesJson["t"]
fecha_values_size = len(fecha_values)
fecha_values_int = []
fecha_values_datetime = []
for x in range(0, fecha_values_size):
fecha_values_int.append(int(fecha_values[x]))
for i in range(0, fecha_values_size):
valor_aux = datetime.fromtimestamp((fecha_values_int[i]))
fecha_values_datetime.append(valor_aux.strftime("%m/%d/%Y"))
data_ordenada = {'Apertura': open_values,
'Cierre': close_values,
'Fecha': fecha_values_datetime}
chart_data = pd.DataFrame(data_ordenada)
source = chart_data
alt_chart = alt.Chart(source).transform_fold(
['Apertura', 'Cierre']
).mark_line().encode(
x=alt.X('Fecha:O',axis=alt.Axis(title="Fechas")),
y=alt.Y('value:Q',scale=alt.Scale(zero=False), axis=alt.Axis(title="Valor")),
tooltip=['Fecha', 'Apertura', 'Cierre'],
color='key:N'
).interactive().properties(
width=800,
height=500
)
st.write("", "", alt_chart)
st.header('Puntos de interés')
st.write(source.describe())
print(accionesJson)
So I'm currently working in a personal project using flask that graphs a user's table and then rendesr it in a different page. However, when I try to do this I get the folowing error: RuntimeError: unsupported value. I have tried all sorts of stuff and none of it has worked. Any help would be appreciated.
Application.py:
from cs50 import SQL
from flask import Flask, flash, jsonify, redirect, render_template, request, session
from flask_session import Session
from tempfile import mkdtemp
from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError
from werkzeug.security import check_password_hash, generate_password_hash
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
from helpers import apology, login_required, toBinary
#configure application
app = Flask(__name__)
#Ensure templates are auto-reloaded
app.config["TEMPLATES_AUTO_RELOAD"] = True
#Ensure responses aren't cached
#app.after_request
def after_request(response):
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Expires"] = 0
response.headers["Pragma"] = "no-cache"
return response
# Configure session to use filesystem (instead of signed cookies)
app.config["SESSION_FILE_DIR"] = mkdtemp()
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Configure CS50 Library to use SQLite database
db = SQL("sqlite:///graph.db")
#login_required
def graph():
#check wether to return user to a form or graph their table
if request.method == "POST":
#define variables
table_name = request.form.get("table_name")
x_axis = request.form.get("x_axis")
y_axis = request.form.get("y_axis")
x_values = list(request.form.get("x_values"))
y_values = list(request.form.get("y_values"))
graph_type = request.form.get("graph_type")
#check wether there is an x value for every y value
if len(x_values) != len(y_values):
return apology("Every x value must have a y value and viceversa", code=400)
#check graph type to use
if graph_type == "line":
plt.plot(x_values, y_values)
elif graph_type == "bar":
height = []
first_value = min(y_values) - 1
for x in y_values:
height.append(x%first_value)
plt.bar(x_values, height)
else:
plt.scatter(x_values, y_values)
plt.xlabel(x_axis)
plt.ylabel(y_axis)
plt.savefig("user_graph")
#set user_graph.png PATH
script_location = Path(__file__).absolute().parent
file_location = script_location / 'user_graph.png'
#pass graph to binary
user_graph = toBinary(file_location)
print(user_graph)
#insert user table into history for later use
db.execute("INSERT INTO history (username, graph, table_name) VALUES(:username, :graph, :table_name)", username=session["username"], graph=user_graph, table_name=table_name)
return render_template("graphed.html")
else:
return render_template("graph.html")
toBinary code:
with open(filename, "rb") as file:
data = file.read()
return data```
To insert a BLOB value the VALUE has to be in the format of x'??????' where ?????? is the byte stream/array as hex values e.g. x'FFFE1266543267890A'. So you need to convert the byte stream/array to such a String and that string could then be used.
I am trying to run python with html using flask locally, i try to render a template within a class object, it compiles but when i try to access it on http://localhost:5000 it gives me 404. Could anyone tell what I'm doing wrong here?
I am trying to display values from a json format using chart.js library.
from flask import Flask
from flask import render_template
import os.path
import json
app = Flask(__name__)
#import the json file
_player_json_file = os.path.join(os.path.dirname(__file__), 'players.json')
def read_players(player_file=None):
if player_file is None:
player_file = _player_json_file
try:
data = json.loads(open(player_file).read())
except IOError:
return {}
#make player dictionary
players = {}
#get player ID from json file = data.
for playerID in data:
players[playerID] = Player_data(data[playerID])
return players
class Players_Data (object):
#app.route("/")
def __init__(self, data):
"""
Assign all the values from the json file to new variables
the values are birth date age weight...
"""
self.player_ID = data['gsis_id']
self.gsis_name = data.get('gsis_name', '')
self.player_fullname = data.get('full_name', '')
self.player_first_name = data.get('first_name', '')
self.player_last_name = data.get('last_name', '')
self.player_weight = data.get('weight','')
self.player_height = data.get('height' , '')
self.player_birth = data.get('birthdate', '')
self.player_pro_years = data.get('years_pro', '')
self.player_team = data.get('data', '')
values = [player_ID,gsis_name,player_fullname,player_first_name,player_last_name,player_weight]
return render_template('chart.html', data=data, values=values)
if __name__ == "__main__":
app.run(host='localhost')
I don't think template rendering is the issue here. You can just return a string from your view as an example.
You get a 404 because that's not how you do classy views in flask. You can have a look here: http://flask.pocoo.org/docs/0.12/views/
But essentially you have to extend from flask.views.View and then manually attach your route to app instance, so it looks something like this:
from flask import Flask
from flask.views import View
app = Flask(__name__)
class Players_Data(View):
def dispatch_request(self):
return 'LOL'
app.add_url_rule('/', view_func=Players_Data.as_view('show_users'))
if __name__ == "__main__":
app.run(host='localhost')
I made a script python app.py and I managed to store data from a javascript form, thanks to a flask app :
app = Flask(__name__)
app.config.from_object('config')
db.init_app(app)
#app.route('/getFormData', methods=['POST'])
def get_javascript_data():
params = request.form.to_dict()
sunElevation = params['sunElevation']
cloudCoverage = params['cloudCoverage']
thresholdNDVI = params['thresholdNDVI']
limitScene = params['limitScene']
city = params['city']
data_search = passData(sunElevation, cloudCoverage, thresholdNDVI, limitScene, city)
return jsonify(data_search.data_dict)
if __name__ == '__main__':
app.run()
Here is the definition of the class passData, in models.py :
class passData:
def __init__(self, sunElevation, cloudCoverage, thresholdNDVI, limitScene, city):
self.sunElevation = sunElevation
self.cloudCoverage = cloudCoverage
self.thresholdNDVI = thresholdNDVI
self.limitScene = limitScene
self.city = city
self.data_dict = [{'sunElevation':self.sunElevation,'cloudCoverage':self.cloudCoverage, 'thresholdNDVI':self.thresholdNDVI, 'limit':self.limitScene, 'city':self.city}]
I need to use those different parameters (sunElevation...) in an other script, in a other folder, to execute a search of imagery and then run the script associated. My problem is that I don't know how to pass those data, because they seem to only exist in the fonction defined in the get_javascript_data().
If someone has an idea that could help me !
You just have to import the other script, call the function and pass the parameters:
app = Flask(__name__)
app.config.from_object('config')
db.init_app(app)
from path.to.your.file import your_function
#app.route('/getFormData', methods=['POST'])
def get_javascript_data():
params = request.form.to_dict()
sunElevation = params['sunElevation']
cloudCoverage = params['cloudCoverage']
thresholdNDVI = params['thresholdNDVI']
limitScene = params['limitScene']
city = params['city']
data_search = passData(sunElevation, cloudCoverage, thresholdNDVI, limitScene, city)
# call the function and pass the parameters
your_function(sunElevation, cloudCoverage) #...
return jsonify(data_search.data_dict)
Try adding the following code in your file, then import the script
import os, sys
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')))
from eosLandviewer.main_naturalite import search