Flask dynamic route is taking values which I have not specified - python

Question
I have created a dynamic route as /update/<randomString> in my Flask app.py file, where randomString is a randomly generated string with the length of 50. However if I search for /update/1 I am able to view the same dynamic route /update/<randomString> without any error! Can anyone explain why is it so?
See what I've tried so far:
#app.route('/')
def index():
randomString = ''.join(secrets.choice(string.ascii_uppercase+string.digits+string.ascii_lowercase) for k in range (50))
session['randomString'] = str(randomString)
return render_template('index.html')
#app.route('/update/<randomString>')
def update(randomString):
if 'randomString' in session:
randomString = session['randomString']
return render_template('update.html')
else:
return 'error...'
Link of the dynamic page at update.html page, where random string is passed with the help of session(defined at index.html page).
Dynamic page
Edit: I am also able to view dynamic route when I click on the link defined above and my URL section shows that long randomString. Problem is: I can access the same route when I search for http://127.0.0.1:5000/update/1
Screenshot one
Screenshot two

While storing the random string, the key you use is randomString. So you are storing the random string in a dict like
session['randomString'] = '1234567890'
Then when you access the session in the /update route you are just checking if session has a key named randomString. You should also check if session['randomString'] == '1234567890' and render the page only if the random string in session is the same as you created in the / path. You can replace the if with
if 'randomString' in session and session['randomString'] == randomString :

Related

How to Update a variable between Flask pages?

I ask a very similar question like this yesterday and was directed here. I took what was posted there (using a session) to take in a user input, update a second page with a data table. However, If I get to that second route through any other means, it resorts back to the default which is an empty data table. So I'm thinking that the variable is not being updated and saved or being rewritten. Code below
#app.route('/', methods=['GET','POST'])
def index():
loadform = LoadDataForm()
session['dataset'] = toy_data.get_empty_df()
if loadform.validate_on_submit():
dataset, headers = toy_data.get_dataset(int(loadform.selectToyData.data))
session['dataset'] = dataset
session.modified = True
return render_template('DataTable.html',dataset=dataset)
return render_template('LoadData.html',form=loadform)
#app.route('/DataTable', methods=['GET','POST'])
def index_data():
dataset = session.get('dataset',None)
return render_template('DataTable.html',dataset=dataset)
The data you are setting is added to the session.
That’s why it’s not set in a different session.

how to send data to html worksheet using flask framework

I have a function calculate_full_eva_web(input:dict) it receives input dictionary several function applied on this input to create calculations dict, after calculations i want to send this data to html dashboard and after send data to html file i can play there with jinja stuff. i am unable to do so, i tried several ways but flask throws error. and also i don't know much about ajax ,may be ajax will do my work, let me know. that is why i am tagging ajax people on this post. Traceback is also attached..Thank you
In simple words, i want to send data to html in flask ! Please check my code. Let me know if i am doing anything wrong.
imports ...
from other file import other_functions
from other file import other_functions_2
from other file import other_functions_3
app = Flask(__name__, template_folder='templates/')
#app.route("/dashboard")
def calculate_full_eva_web(input:dict):
calculate_gap = other_functions(input)
calculate_matrix = other_functions_2(input)
average = other_functions_3(input)
data = dict{'calculate_gap':calculate_gap, 'calculate_matrix':calculate_matrix,'average':average}
return render_template('pages/dashboard.html', data = data)
if __name__ == "__main__":
app.run(debug=True)
The route receive a dict as input so you must change #app.route("/dashboard") to #app.route("/dashboard/<input>") and pass input to the route in the link of the route.
For example, I have a route as below.
#app.route('/user/<name>')
def user(name):
return render_template('home.html', name=name)
To pass name to the route, I access the link http://localhost:5000/user/myname.

Error 404 on flask

When I run the server.py which is hosted on 127.0.0.1:5000 it generates the list of articles
#app.route("/")
def articles():
"""Show a list of article titles"""
return render_template('articles.html', my_list= Alist)
The code above generates the list of articles and is running properly when I run 127.0.0.1:5000, the list is displayed.
#app.route("/article/<topic>/<filename>")
def article(topic,filename):
"""
Show an article with relative path filename. Assumes the BBC structure of
topic/filename.txt so our URLs follow that.
"""
for art in articles_table:
if art[0]== "%s/%s" %(topic, filename):
title_str = art[1]
text_list = art[2].split('\n')
text_list = [t.lower() for t in text_list if len(t) >= 1]
rec = recommended(art[0], articles_table, 5)
break
return render_template('article.html', title=title_str, text=text_list,
fiveA= rec)
However, whenever I click on any of the articles it redirects to http://127.0.0.1:5000/article/data/bbc/business/003.txt
and generates error 404 but the file is present at a particular path in the local directory
I believe the error is in the 2nd code snippet.
I'm a beginner to flask so I'm really confused as to what to do. Any help will be appreciated
If I understand correctly you are trying to catch the topic and the filename in the route. The problem is the URL you're trying to access doesn't match the route you have defined.
You have 2 options:
Change the link so the URL is http://127.0.0.1:5000/article/business/003.txt. By doing this you'll be able to keep the same route you currently have #app.route("/article/<topic>/<filename>"). Here topicwill have the value of "business" and filename will have the value of "003.txt".
Or you can leave the link so the URL stays the same (http://127.0.0.1:5000/article/data/bbc/business/003.txt) and you can change your route to look like this: #app.route("/article/data/bbc/<topic>/<filename>"). Again topic will have the value of "business" and filename will have the value of "003.txt".
You can find more information about routes here

Runtime Error - web.config

I have created a website using flask that takes in a string, creates a url based off the string, parses the url and then feeds it back into the website. I created a function to do so and it works perfectly. However when I implement it within my flask program it started throwing a runtime error that states:
An application error occurred on the server. The current custom error settings for this application prevent the details of the application error from being viewed remotely (for security reasons). It could, however, be viewed by browsers running on the local server machine.
Details:To enable the details of this specific error message to be viewable on remote machines, please create a customErrors tag within a "web.config" configuration file located in the root directory of the current web application. This customErrors tag should then have its "mode" attribute set to "Off".
I am not familiar with creating a web.config or how to implement this within my flask program. Any help would be appreciated.
Code:
Function that works when ran on it's own:
def parse_wotc():
set_list = []
# Manually enter in value for test
card_url = 'http://gatherer.wizards.com/Pages/Card/Details.aspx?name=' +
'mountain' # (replace mountain) card_name.replace(' ', '+')
soup = BeautifulSoup(requests.get(card_url).text, 'html.parser')
for image in soup.find_all('img'):
if image.get('title') is not None:
set_list.append(image.get('title'))
print(set_list)
return set_list
webapp code:
#app.route('/', methods=['GET', 'POST'])
def index():
card_name = None
card_url = '/static/images/card_back.jpg'
if request.form.get('random_button'):
card_url, card_name = random_card_image(list_card_names)
# When function ran here it give the error
parse_wotc(card_name)
def random_card_image(list_card_names):
"""This function will pull a random card name from the provided list and
return to main program"""
card_name = random.choice(list_card_names)
card_url = 'http://gatherer.wizards.com/Handlers/Image.ashx?name=' +
card_name.replace(' ', '+').lower() + \
'&type=card'
return card_url, card_name
It took a couple of hours to determine what the issue was, but it is working now. The issue is that I made a text file that had a list of card names that I was pulling from to create a random selection - the text file however included a trailing \n on each entry. Therefore it was creating a url with \n in it which was unnoticeable at the time and causing an error. I used rsplit() when creating the name list to remove the trailing \n and now it works perfectly.

Passing objects through Flask URL's

I am working on a site using Flask that is pulling data from an API, processing it into JSON, and then dynamically loading it throughout the site as needed. I am having an issue with matching the URL appropriately while at the same time efficiently loading what data I need.
Here is my main file:
import requests
from flask import Flask, render_template
app = Flask(__name__)
url = 'https://omgvamp-hearthstone-v1.p.mashape.com/cards'
myHeaders={
"X-Mashape-Key": 'key-here',
"Accept": "application/json"
}
r = requests.get(url, headers=myHeaders)
cards = r.json()
badSets = ['Promo', 'Hall of Fame', 'Tavern Brawl', 'Hero Skins', ' Missions', 'Credits', 'System', 'Debug']
#app.route('/')
def index():
return render_template('index.html', cards=cards, badSets=badSets)
#app.route('/<setName>', methods=['GET'])
def set(setName):
return render_template('set.html', cards=cards, setName=setName, badSets=badSets)
#app.route('/<setName>/<cardName>', methods=['GET'])
def individualCard(setName, cardName):
return render_template('card.html', cards=cards, setName=setName, cardName=cardName, badSets=badSets)
First, I'd prefer to not have to pass each html page all of my data. Is there some way to pull only what is needed and ignore the rest?
Second, I would like to pass a dictionary object i.e.
if card['name'] == card[setName][--index--][cardName]:
pass card object to html page here
How could this be achieved, and is it possible without having to use a for-loop through all of my data?
I'm happy to load my html pages if needed.
Assuming the basic structure of your parsed json data looks like this (a dictionary with lists of dictionaries):
{
"Basic": [{"cardId": 4711, ...}, {"cardId": 4712, ...}, ...],
"Fancy": [...],
...
}
You could rewrite:
#app.route('/<setName>', methods=['GET'])
def set(setName):
cardset = cards.get(setName)
return render_template('set.html', cardset=cardset)
This extracts the card set we are looking for by the dictionary key, according to the assumed data structure above.
Then in the template, instead of cardName, pass the cardId and rewrite the other route:
#app.route('/<setName>/<cardId>', methods=['GET'])
def individualCard(setName, cardId):
cardset = cards.get(setName)
matches = [x for x in cardset if x['cardId'] == cardId]
card = matches[0]
return render_template('card.html', card=card)
This uses list comprehension to extract a list of matches (everything that has the cardId we are looking for) from our selected cardset, and should be a list with a single element. We return the first element to the template for rendering.
Now this obviously does not do any error checking, for example the dictionary key we passed might be wrong and not be found, the cardId might not be found, or more interestingly there might be more than one result for the cardId we passed.
But this would be the general idea on how to approach this.
Also note I've left out badSets for clarity in the example, I'm assuming this are card sets that are forbidden, or for testing purposes.
For this case, you'd want to check the dictionary key first before looking up the set, and show an error page or something maybe:
#app.route('/<setName>', methods=['GET'])
def set(setName):
if setName in badSets:
return render_template('error.html')
cardset = cards.get(setName)
return render_template('set.html', cardset=cardset)
Disclaimer: This is coming purely from memory and it is late, so there might be an error here or there...

Categories