I want to put a button on a flask-generated web page and let a user download the html page as a file when the user clicks the button. What I imagine is something like saving the rendered html into BytesIO and send it via send_file, but I can't find how to save the rendered page into a file object. How can I do that?
You could try something like this:
import StringIO
from flask import Flask, send_file, render_template
def page_code():
strIO = StringIO.StringIO()
strIO.write(render_template('hello.html', name='World'))
strIO.seek(0)
return send_file(strIO,
attachment_filename="testing.txt",
as_attachment=True)
It is not tested but should give you an idea.
#gtomer Using the input from the thread, I may have figured out a solution that helped eliminate the AssertionError (by using BytesIO since on StringIO) that worked for me. This is on Python39.
xx = asteriod.query.filter_by(order_number=tagVV).first()
yy = toposphere.query.filter_by(order_number=tagVV).all()
apple = io.BytesIO()
apple.write(render_template("receipt2.html", x12=yy, x13=ww, x14=xx).encode('utf-8'))
apple.seek(0)
return send_file(apple, attachment_filename="testing.html", as_attachment=True)
Related
This question already has answers here:
Serve static files from a CDN rather than Flask in production
(3 answers)
Closed 1 year ago.
I'm using a web server on PythonAnywhere to run a Flask application. All I'm looking to do is randomly output a gif from a list of URLs. I'm looking to utilize the requests library, and I suspect I need the render_template in order to actually pass the image over. I have been dealing with either view function TypeErrors or outputs of plain text to a URL. I've also incorporated PIL and shutil once or twice but to no functional success.
from flask import Flask, render_template
import random
import requests
app = Flask(__name__)
WELCOME_LIST = [
'https://cdn.discordapp.com/attachments/891856529928622080/891865614870806568/rgb.gif'
'https://cdn.discordapp.com/attachments/891856529928622080/891865655542964224/racing.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891897881550802954/comet.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891897942678581278/harujion.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898027126698045/letter.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898085909864479/encore.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898143627677786/gunjou.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898187240050718/haruka.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898241900236830/monster.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898276339646474/probably.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898352617259028/taisho.gif',
'https://cdn.discordapp.com/attachments/891856529928622080/891898425342316624/tracing.gif',
]
#app.route('/')
def obtainGif():
gif = random.choice(WELCOME_LIST)
response = requests.get(gif)
return response.raw
#app.route('/join')
def output():
finalize = obtainGif
return render_template('home.html', finalize=finalize)
if __name__ == '__main__':
app.run(host='0.0.0.0')
Use the send_file method.
from flask import Flask, render_template, send_file
def obtainGif():
gif = random.choice(WELCOME_LIST)
response = requests.get(gif, stream=True)
return send_file(response.raw, mimetype='image/gif')
You can use {{ variable }} anywhere in your template, not just in the HTML part.
def output():
gif = random.choice(WELCOME_LIST)
return render_template('home.html', gif=gif)
in the home.html file add a script tag in which you are capturing this passed data
<script>
let gif= {{gif|safe}};
</script>
At this point you have the GIF URL inside your java-script code from where you can edit the HTML part of your code to add this GIF inside the <img> tags
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'm using Flask-Uploads to upload a file and output the URL. However, for some reason the URL always points to a 404! I can see the file in the correct folder, but the URL seems to not be able to find it. Here are the configurations I'm using...
UPLOADS_DEFAULT_URL = os.environ.get("UPLOADS_URL", "http://localhost:5000/")
UPLOADS_DEFAULT_DEST = "app/uploads"
I also have an Upload set defined as:
productUploadSet = UploadSet('plist', extensions=('xlsx', 'csv', 'xls'))
The file is found in "app/uploads/plist/filename.csv" and I'll get a url returned to me like "http://localhost:5000/productlist/filename.csv" but whenever I open the URL it is always a 404. I know that the url method from Flask-Uploads doesn't actually check fi the file exists, but I can see the file is actually there. Is it looking in the wrong place somehow? Thanks for any help.
From Flask's guide to uploading files:
Now one last thing is missing: the serving of the uploaded files. As of Flask 0.5 we can use a function that does that for us:
from flask import send_from_directory
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
Alternatively you can register uploaded_file as build_only rule and use the SharedDataMiddleware. This also works with older versions of Flask:
from werkzeug import SharedDataMiddleware
app.add_url_rule('/uploads/<filename>', 'uploaded_file',
build_only=True)
app.wsgi_app = SharedDataMiddleware(app.wsgi_app, {
'/uploads': app.config['UPLOAD_FOLDER']
})
Without implementing one of these, Flask has no idea how to serve the uploaded files.
Does anyone know if flask redirect is able to open a link / URL in a new tab?
#app.route('/test')
def my_page():
return redirect('http://mylink.com', 301)
I would like if the mylink website opened in a new tab, any insights?
As far as I know that would not be a flask issue. You have to open a new tab within your html code or with Javascript.
example:
Link
The server has no power over what the browser does in this case.
You could also use Python's webbrowser module to open a page, if you'd like to avoid getting into the HTML
import webbrowser
#app.route('/test')
def my_page():
return webbrowser.open_new_tab('http://mylink.com')
If you're dealing with a form you can set target="_blank"
A slight adjustment to #garettmd that fixes #John Jiang's issue:
import webbrowser
from flask import Flask, redirect, url_for
#app.route("/test/")
def test():
webbrowser.open("https://google.com")
return redirect(url_for("index"))
This way we get to return a redirect (which we should probably do anyway) and we also get our new tab without "The view function did not return a valid response" error.
When I run this code on my computer with the help of "Google App Engine SDK", it displays (in my browser) the HTML code of the Google home page:
from google.appengine.api import urlfetch
url = "http://www.google.com/"
result = urlfetch.fetch(url)
print result.content
How can I make it display the page itself? I mean I want to see that page in my browser the way it would normally be seen by any user of the internet.
Update 1:
I see I have received a few questions that look a bit complicated to me, although I definitely remember I was able to do it, and it was very simple, except i don't remember what exactly i changed then in this code.
Perhaps, I didn't give You all enough details on how I run this code and where I found it. So, let me tell You what I did. I only installed Python 2.5 on my computer and then downloaded "Google App Engine SDK" and installed it, too. Following the instructions on "GAE" page (http://code.google.com/appengine/docs/python/gettingstarted/helloworld.html) I created a directory and named it “My_test”, then I created a “my_test.py” in it containing that small piece of the code that I mentioned in my question.
Then, continuing to follow on the said instructions, I created an “app.yaml” file in it, in which my “my_test.py” file was mentioned. After that in “Google App Engine Launcher” I found “My_test” directory and clicked on Run button, and then on Browse. Then, having visited this URL http://localhost:8080/ in my web browser, I saw the results.
I definitely remember I was able to display any page in my browser in this way, and it was very simple, except I don’t remember what exactly I changed in the code (it was a slight change). Now, all I can see is a raw HTML code of a page, but not a page itself.
Update 2:
(this update is my response to wescpy)
Hello, wescpy!!! I've tried Your updated code and something didn't work well there. Perhaps, it's because I am not using a certain framework that I am supposed to use for this code. Please, take a look at this screen shot (I guess You'll need to right-click this image to see it in better resolution):
(source: narod.ru)
Is not that easy, you have to parse content and adjust relative to absolute paths for images and javascripts.
Anyway, give it a try adding the correct Content-Type:
from google.appengine.api import urlfetch
url = "http://www.google.com/"
result = urlfetch.fetch(url)
print 'Content-Type: text/html'
print ''
print result.content
a more complete example would look something like this:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import urlfetch
class MainHandler(webapp.RequestHandler):
def get(self):
url = "http://www.google.com/"
result = urlfetch.fetch(url)
self.response.out.write(result.content)
application = webapp.WSGIApplication([
('/', MainHandler),
], debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
but as others' have said, it's not that easy to do because you're not in the server's domain, meaning the pages will likely not look correct due to missing static content (JS, CSS, and/or images)... unless full pathnames are used or everything that's needed is embedded into the page itself.
UPDATE 1:
as mentioned before, you cannot just download the HTML source and expect things to render correctly because you don't necessarily have access to the static data. if you really want to render it as it was meant to be seen, you have to just redirect... here's the modified piece of code:
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.api import urlfetch
class MainHandler(webapp.RequestHandler):
def get(self):
url = "http://www.google.com/"
self.redirect(url)
application = webapp.WSGIApplication([
('/', MainHandler),
], debug=True)
def main():
run_wsgi_app(application)
if __name__ == '__main__':
main()
UPDATE 2:
sorry! it was a cut-n-paste error. now try it.
special characters such as <> etc are likely encoded, you'd have to decode them again for the browser to interpet it as code.