Similiar routes/pages in Flask - how to remove duplication - python

I have got a few subpages which look very similiar:
They are almost the same but each of them presents different currency:
#app.route('/', methods=['POST', 'GET'])
#app.route('/dollar', methods=['POST', 'GET'])
def dollar_page():
form = MyTextForm()
if form.validate_on_submit():
values = app.process(request.form["values"])
labels = get_data()
return render_template('currency.html', currency="dollar", labels=labels, values=values)
#app.route('/euro', methods=['POST', 'GET'])
def euro_page():
form = MyTextForm()
sentiment = ""
if form.validate_on_submit():
values = app.process(request.form["values"])
labels = get_data()
return render_template('currency.html', currency="euro", labels=labels, values=values)
#app.route('/pound', methods=['POST', 'GET'])
def pound_page():
... etc ...
What is the best way to get rid of this duplication in Flask applications? Is there any pattern? Thanks!

Create a variable in your route to receive the type of currency. The route variable is passed as an argument to the view function. The / route doen't have the variable, so provide a default in that case.
import functools
def verify_currency(f):
#functools.wraps(f)
def wrapper(currency_type):
if currency_type not in ['dollars', 'euros']: #can add more currencies to list later
return flask.render_template("error.html") #or redirect
return f(currency_type)
return wrapper
#app.route('/', methods=['POST', 'GET'], defaults={'currency': 'euro'})
#app.route('/currency/<currency>', methods=['POST', 'GET'])
#verify_currency
def dollar_page(currency):
form = MyTextForm()
values = labels = None
if form.validate_on_submit():
values = app.process(request.form["values"])
labels = get_data()
return render_template('currency.html', currency=currency, labels=labels, values=values)

Related

Flask error : Method Not Allowed The method is not allowed for the requested URL

I am making project on movie recommendation system using flask and i added login page when i click on login it shows
Method Not Allowed The method is not allowed for the requested URL.
"m getting the following error whenever I try to submit data to my Flask form:
Method Not Allowed The method is not allowed for the requested URL.
Relevant parts of my code are as follows:
when i click on login it shows error method Not allowed.
help regarding this solution.
"
#auto complete some movies
def get_suggestions():
data = pd.read_csv("tmdb.csv")
return list(data["title"].str.capitalize())
app = Flask(__name__)
#main page
#app.route("/index", methods=["GET", "POST"])
def index():
NewMovies = []
with open("movieR.csv", "r") as csvfile:
readCSV = csv.reader(csvfile)
NewMovies.append(random.choice(list(readCSV)))
m_name = NewMovies[0][0]
m_name = m_name.title()
with open("movieR.csv", "a", newline="") as csv_file:
fieldnames = ["Movie"]
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writerow({"Movie": m_name})
result_final = get_recommendations(m_name)
names = []
dates = []
ratings = []
overview = []
types = []
mid = []
for i in range(len(result_final)):
names.append(result_final.iloc[i][0])
dates.append(result_final.iloc[i][1])
ratings.append(result_final.iloc[i][2])
overview.append(result_final.iloc[i][3])
types.append(result_final.iloc[i][4])
mid.append(result_final.iloc[i][5])
suggestions = get_suggestions()
return render_template(
"index.html",
suggestions=suggestions,
movie_type=types[5:],
movieid=mid,
movie_overview=overview,
movie_names=names,
movie_date=dates,
movie_ratings=ratings,
search_name=m_name,
)
#login code
#app.route("/")
#app.route("/login", methods=["GET", "POST"])
def login():
if flask.request.method == "POST":
un = request.form["username"]
pwd = request.form["password"]
if un not in database:
return flask.render_template("login.html", info="Invalid User")
else:
if database[un] != pwd:
return flask.render_template("login.html", info="Invalid Password")
else:
return render_template("index.html")
return render_template("login.html")
if __name__ == "__main__":
app.run()
You didn't specify methods in #app.route("/").
New Code:
#app.route("/", methods=["GET", "POST"])
#app.route("/login", methods=["GET", "POST"])
def login():
if flask.request.method == "POST":
un = request.form["username"]
pwd = request.form["password"]
if un not in database:
return flask.render_template("login.html", info="Invalid User")
else:
if database[un] != pwd:
return flask.render_template("login.html", info="Invalid Password")
else:
return render_template("index.html")
return render_template("login.html")

perform GET Request with output from POST Request in Flask

I have this Flask View which takes a POST and GET requests
Goal is to do something with the Data from the POST request
and use it for the GET request
for example this AJAX GET Request
$.getJSON({url: '/uploadajax'}).done(result =>console.log(result));
which waits to return the processed data from the POST request
I was able to pass the data to the AJAX call by
declaring the global variable result and changed it in the function
and use it as a return value for the GET Request
Question here: is there a cleaner way to perform this task ?
result = 0
# ------------upload-file-----------------------------------------#
#flask_class.route('/uploadajax', methods=['POST', 'GET'])
def receave_file():
if request.method == 'POST':
uploaded_file = request.files['file']
# filename = secure_filename(uploaded_file.filename)
if uploaded_file.filename != "":
filename = secure_filename(uploaded_file.filename)
file_ext = os.path.splitext(filename)[1] # was macht das ?
if file_ext not in Config.ALLOWED_EXTENSIONS:
abort(400)
# file kann auch net gespeichert werden
uploaded_file.save(os.path.join(flask_class.instance_path, 'uploads', filename))
# ------------------------------------- #
df = pd.read_excel(uploaded_file)
columns = df.columns.to_list()
global result
result = json.dumps(columns)
# return result
print("shoud return somehting")
# ---------------------------------------- #
return '', 204
# ---------------------------------------- #
else:
return "false"
else:
# GET REQUEST
if len(result) > 1:
return result
else:
return '', 404
# return render_template('index.html')
Yes, there is :)
Have a look at the following code:
class LocalStore:
def __call__(self, f: callable):
f.__globals__[self.__class__.__name__] = self
return f
# ------------upload-file-----------------------------------------#
#flask_class.route('/uploadajax', methods=['POST', 'GET'])
#LocalStore() # creates store for this unique method only
def receave_file():
if request.method == 'POST':
LocalStore.post_headers= request.headers
LocalStore.post_body = request.body
LocalStore.post_json = request.get_json()
LocalStore.post_params = request.params
LocalStore.answer_to_everything = 42
print("POST request stored.")
return jsonify({"response": "Thanks for your POST!"})
else:
try:
print("This is a GET request.")
print("POST headers were:", LocalStore.post_headers)
print("POST params were :", LocalStore.post_params)
print("POST body was :", LocalStore.post_body)
print("The answer is :", LocalStore.answer_to_everything)
return jsonify({"postHeadersWere": LocalStore.post_headers})
except AttributeError:
return jsonify({"response":"You have to make a POST first!"})
I created a special class which "injects" its reference into the __globals__ dictionary of the method. If you type the class name in the method, it will be the object reference, not the class reference. Be aware of that!
You then just need to add #LocalStore underneath the #app.route(...) of your application because the store needs to be routed with the method...
I think it's a quite elegant way that saves you the definition of 5 global variables for 5 different methods

How to pass a list from one function to another in Flask?

I have created a function that returns a list a list of scores. now I want that list to be used in another function
here is my app.py file
#app.route('/getmarks', methods=['GET', 'POST'])
def getmarks():
if request.method == 'POST':
marks = list(map(float,(request.form['score']).split()))
return render_template('results.html', marks=marks)
return render_template('getmarks.html')
#app.route('/displaygraph/marks', methods=['GET', 'POST'])
def displaygraph(marks):
return render_template('graphs.html', marks=marks)
How do I get that marks list in my displaygraph function?

How to pass variable onto another route in FLASK

I am trying to pass a variable from one route to another, but I am unable to. Can someone guide me on doing it? I get the error on the last line.
#app.route("/search", methods=['GET', 'POST'])
def search():
if request.method == 'GET':
return render_template('search.html', navbar=True)
else:
query = request.form.get('query').lower()
query_like = '%' + query + '%'
books = db.execute('SELECT * FROM books WHERE (LOWER(isbn) LIKE :query) OR (LOWER(title) LIKE :query) '
'OR (LOWER(author) LIKE :query)',
{'query': query_like}).fetchall()
if not books:
return render_template('error.html', message='No Books were Found!', navbar=True)
return render_template('books.html', query=query, books=books, navbar=True)
#app.route("/books", methods=['GET', 'POST'])
def books():
return render_template('books.html', query=query, books=books)
The problem is the way your code is organized. Variables in a function are scoped within the function, so books isn't available from the second route. In addition to that, you have a naming collision where books=books is referring to the function itself (which is defined at the module scope).
If you want to share code between routes, put it in a separate function:
def get_books(query, show_nav_bar=False):
query = query.lower()
query_like = '%' + query + '%'
books = db.execute('SELECT * FROM books WHERE (LOWER(isbn) LIKE :query) OR (LOWER(title) LIKE :query) '
'OR (LOWER(author) LIKE :query)', {'query': query_like}).fetchall()
if not books:
return render_template('error.html', message='No Books were Found!', navbar=True)
return render_template('books.html', query=query, books=books, navbar=show_nav_bar)
#app.route("/search", methods=['GET', 'POST'])
def search():
if request.method == 'GET':
return render_template('search.html', navbar=True)
else:
return get_books(request.form.get('query'), show_nav_bar=True)
#app.route("/books", methods=['GET', 'POST'])
def books():
return get_books(request.form.get('query'))

Flask render_template context not showing in URL

I am trying to pass params to the URL in flask, but I can not get them to show up for anything.
#logout.route('/logout')
def logout_page():
current_provider = current_oauth_user.get_provider()
return render_template('index.html', provider=current_provider)
I expect to see /logout?provider=facebook but I just get /logout
Right now I am doing this:
#logout.route('/logout')
def logout_page():
provider = request.args.get('provider')
current_provider = current_oauth_user.get_provider()
if not provider and current_provider:
return redirect(url_for('logout.logout_page',
provider=current_provider))
return render_template('index.html')
but that just seems so terrible.
You should return some value using '/logout' path.
So at first, you use render_template(index.html) under def main(). Then you create def logout_page() and return some value ( in your case is current_provider).
#app.route('/')
def main():
return render_template('index.html')
#app.route('/logout')
def logout_page():
current_provider = current_oauth_user.get_provider()
return current_provider
if __name__=="__main__":
app.run(port=8000)

Categories