I am trying to write a dynamic page in Python with Flask on my pythonanywhere.com free hosting. I have the following code, hoping I could write to the resp variable to make my pages.
#app.route('/xdcc-search/search.html')
def search_app():
try:
with open('templates/xdcc-search/search.html', 'r') as dynamic:
dynamic.read()
except:
pass
dynamic.replace("<file>","MY_FILENAME.tar")
resp = make_response(render_template(dynamic), 200)
no_cache(resp)
return resp
I get an error stating dynamic is referenced before assignment. Is there a way to edit the template after render_template(filename) retreives and assembles the page?
When you do this:
with open('templates/xdcc-search/search.html', 'r') as dynamic:
dynamic.read()
...you are reading in the contents of the file, but you are throwing them away -- read() is a function that reads the contents of the file and returns them.
Fixing your code so that it actually does what you are trying to do gives this:
#app.route('/xdcc-search/search.html')
def search_app():
try:
with open('templates/xdcc-search/search.html', 'r') as dynamic:
contents = dynamic.read()
except:
pass
contents.replace("<file>","MY_FILENAME.tar")
resp = make_response(render_template(contents), 200)
no_cache(resp)
return resp
...but that is still wrong; render_template takes as its parameter the name of the file that contains the template, not its contents. So what you need to do to get this working would be to replace that render_template with render_template_string.
#app.route('/xdcc-search/search.html')
def search_app():
try:
with open('templates/xdcc-search/search.html', 'r') as dynamic:
contents = dynamic.read()
except:
pass
contents.replace("<file>","MY_FILENAME.tar")
resp = make_response(render_template_string(contents), 200)
no_cache(resp)
return resp
But this is still not using Flask templates the way they are meant to be used. The point of templates is that they should contain things in curly brackets to specify what changes should be made. Replacing a static string inside one with an explicit call to replace bypasses that and does a more primitive version of the same thing.
What you really should be doing is changing your template so that instead of having <file> inside, it, it has {{ file }}, and then you can replace all of that messy view code with this:
#app.route('/xdcc-search/search.html')
def search_app():
resp = make_response(render_template("xdcc-search/search.html", file="MY_FILENAME.tar"), 200)
no_cache(resp)
return resp
Finally, I'm not sure that you need that no_cache, as view functions are not cached by default. Also, the default status code on a response is 200. So probably all you need is this:
#app.route('/xdcc-search/search.html')
def search_app():
return render_template("xdcc-search/search.html", file="MY_FILENAME.tar")
Related
#app.get("/drogaraia")
def scraperaia(urlbase="https://www.drogaraia.com.br/medicamentos",maximodepaginas=10):
listaprincipal= []
pagina=2
contador=1
while pagina<maximodepaginas:
testeurl= ((urlbase)+".html?p="+str(pagina))
page = requests.get(testeurl)
results= BeautifulSoup(page.content,"html.parser")
remedios = results.find_all("div",class_="container")
for remedio in remedios:
try:
link=(remedio.find("a", class_="show-hover"))['href']
preco=remedio.find(class_="price").getText().strip()
titulo=(remedio.find("a", class_="show-hover")).getText()
categoria=urlbase.rsplit('/',1)[-1]
listaremedio=[{'link':link,'preco':preco,'titulo':titulo,'categoria':categoria}]
listaprincipal.extend(listaremedio)
except:
pass
contador=contador+1
pagina=pagina+1
return(listaprincipal)
#app.get("/drogaraia/medicamentos/monitores-e-testes/teste-de-controle-glicemicos")
scraperaia(urlbase="https://www.drogaraia.com.br/medicamentos/monitores-e-testes/teste-de-controle-glicemicos",maximodepaginas=10)
Error message here:
scraperaia(urlbase="https://www.drogaraia.com.br/medicamentos/monitores-e-testes/teste-de-controle-glicemicos",maximodepaginas=10)
^^^^^^^^^^
SyntaxError: invalid syntax
I don't see how it can be wrong syntax. I have tried not assigning the variables inside the scraperaia() function, like so:
urlbase="https://www.drogaraia.com.br/medicamentos/monitores-e-testes/teste-de-controle-glicemicos"
maximodepaginas=10
scraperaia(urlbase,maximodepaginas)
and it still doesnt work.
The last two lines of your provided code are wrong. You need to use def to define a function.
You can define multiple routes bound to the same function. If you would like to know which route was used, you can use the Request object to get the request URL path (see documentation here and here). Working example below:
from fastapi import FastAPI, Request
app = FastAPI()
#app.get("/store")
#app.get("/store/monitors-and-tests")
def main(request: Request, baseurl: str = "https://someurl", maxpages: int = 10):
return {"Called from": request.url.path}
I have a webapp with the following code, which is supposed to serve up any .html file I have stored in the htmls/ directory, provided the two parameters urlhash and predictiontag are correct.
import web
urls = (
'/htmlview/(.*)', 'htmlview'
)
class htmlview:
def GET(self, urlhash, predictiontag):
cache_dir = os.path.join("htmls\\", urlhash)
htmlpath = os.path.join(cache_dir, predictiontag + ".html")
with open(htmlpath, "r", encoding="utf-8") as f:
data = f.read()
return data
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
I don't know how to format the GET request from a browser window in order to actually access these files. I tried http://localhost:8080/htmlview/a?urlhash=6355865449554195623&predictiontag=Primary but it gave me the error:
<class 'TypeError'> at /htmlview/a
GET() missing 1 required positional argument: 'predictiontag'
For reference, here is the other post I was following: How to serve file in webpy?
I use flask but I am guessing that webpy wants you to specify multiple groups in the url matching pattern. (.*) probably matches the whole query string as a single argument to the GET function. Maybe you can use something like
urls = ('/htmlview/(.*)&(.*)', 'htmlview')
Again, just guessing.
After some trial and error, here is what worked for me:
urls = (
'/htmlview/(.*)/(.*)', 'htmlview'
)
class htmlview:
def GET(self, urlhash, predictiontag):
cache_dir = os.path.join("htmls\\", urlhash)
htmlpath = os.path.join(cache_dir, predictiontag + ".html")
with open(htmlpath, "r", encoding="utf-8") as f:
data = f.read()
return data
It seems web.py automatically takes the first /(.*) to be the first parameter and the second to be the second parameter.
Use urls regular expression to match url path.
Use web.input() to access query string.
For your example url: http://localhost:8080/htmlview/a?urlhash=6355865449554195623&predictiontag=Primary
url = ( '/htmlview/(.*)', 'htmlview', )
Will pass only 'a' as the first parameter to htmlview.GET(). The remainder is obtainable within htmlview.GET() using web.input():
class htmlview:
def GET(self, path):
urlhash = web.input().urlhash
predictiontag = web.input().predictiontag
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.
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...
I'm stuck with how to retrieve a parameter inside a URL, using GAE, Python, webapp2.
In my main.py file I have a template that constructs a url, something like this:
.../products?p=12345
In app.yaml I dispatch to products.py with:
- url: /products.*
script: products.application
In products.py I have different request handlers, with the URL above, the user is routed to the 1st one:
application = webapp2.WSGIApplication([
('/products', ProductsPage),
('/products-save', SaveProduct),
('/products-find', FindProduct),
('/products-delete', DeleteProduct),
('/products-search', SearchProducts),
], debug = True)
In ProductsPage I do the following:
class ProductsPage(webapp2.RequestHandler):
def get(self):
p1 = self.request.get('p')
But for p1 I just get an empty string.
Any ideas what I'm overlooking?
Thanks in advance!
Try this:
p1 = self.request.GET['p']
It will return the last occurrence of the p being passed to request, at default request.get() only returns the first occurrence of p, which you may have passed multiple times somewhere from your request.
Or try adding allow_multiple=True and it will return ALL p values being passed, in a list:
p1_list = self.request.get('p', allow_multiple=True)
for p1 in p1_list:
... check the value inside this list ...