Why download button on Python website doesn't work - python

I have Flask website in which I want to add download button which downloads .csv file with scraped data.
In my html file I have this code:
<a href="cms_scrape.csv" ><button>Download!</button></a>
And only output I get is error: The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.
File is in its proper folder.
My folder structure:
└───Project
│ cms_scrape.csv
│
└───templates
index.html

You will need to specify some sort of route on the backend of your site.
For instance, somewhere in your flask site, you probably have a route #app.route('/') for your index. You will need a similar route for your file. That route will go out onto your file system and return the file itself.
#app.route('/csv_file')
def csv_file():
return flask.send_file('path/to/file/cms_scrape.csv',
attachment_filename='cms_scrape.csv',
as_attachment=True)
You will also need to modify your html to access a route and not the file name directly (unless you create your routes dynamically, of course):
<a href="/csv_file" ><button>Download!</button></a>

Not exactly sure about this but I think the tag has a download attribute you can use. Then you don't need the button.
Usage:
<a href="/path/to/file" download>
Source: https://www.w3schools.com/tags/att_a_download.asp

You can make links to files with the
{{ url_for('static', filename='filename.foo') }}
function inside your template. You have to store the file in a folder named 'static' which should be located in the directory where the main scipt is.
The link in your template should look like this:
<a href=" {{ url_for('static', filename='cms_scrape.csv') }} " download>Download!</a>

Related

Why URLs from 'static' does not working for preview in flask?

I am trying to show some preview in Flask from user-uploaded images static/uploads and found that URLs generated by url_for('static', filename=image_file_path) do not work as I'd like.
I am getting out a path like: /static/uploads/0321.jpg
and after putting it in HTML img src={{ image_url_list[0] }} I see no preview (with URL: http://127.0.0.1:5000/static/uploads/0321.jpg if I copy the empty image address)
It is 404 error:GET /static/uploads/03020011.jpg HTTP/1.1" 404 -
The file is in its place and I can access it inside the App if remove the first slash static/uploads/0321.jpg
Actually, I'd like to get the working URLs not only for preview but have them externally visible for other sites (but not freely explorable by other users just typing static/uploads in browser).
So, please, advise me what am I doing wrong?

Get user input via for loop for python script in a Flask application

I am trying to create a very simple one-page Flask application for a python script that I have. The script requires multiple user inputs in a for-loop with the number of loops being user input as well.
Here is the code in my script to make it more clear:
def shared_books():
import requests as re
from bs4 import BeautifulSoup
import time
num_lists = int(input('Enter the number of lists you would like to search:'))
urls = []
page_counts = []
for i in range(num_lists):
urls.append(input(f'Enter the url for list {i + 1}:'))
page_counts.append(int(input(f'Enter the number of pages for list {i + 1}:')))
I want a simple HTML that will ask the user for the number of lists, then the URL and page count for each list as is shown in my function. Then it will run the entire function.
The HTML code I have right now is super simple and I don't want much else outside of the input parts:
<html>
<head>
<title>Goodreads-App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<<p>This app will allow you to see books that are
shared between multiple lists on goodreads</p>
</body>
</html>
Please let me know how I can set up this application!
Firstly, I suggest you take a look at the Flask docs. You are doing it right in terms of having a view function, but the input() python keyword doesn't work like that in Flask. Instead, you should render an html template which you can then put your form input field into. Here is an example:
from flask import Flask, render_template
#flask initialising stuff, read docs for info
#app.route("/home")
def home():
return render_template("home.html")
Flask runs on your computer's local server "localhost", which is not publicly accessible. It conventionally runs on port 5000, which gives the name "localhost:5000".
When someone visits "localhost:5000/home", flask will look for a file called "home.html" in a pre-designated templates folder – the default is a directory called "templates" which you should put your html files into.
So if this is your "home.html" file:
<html>
<head>
<title>Goodreads-App</title>
</head>
<body>
<h1>Welcome to my app!</h1>
<p>This app will allow you to see books that are
shared between multiple lists on goodreads</p>
</body>
</html>
When you load the page associated with a specific function, it will return a template which is rendered as html. The above should look something like this:
And that is how to start.
Thank you for the answers! I haven't quite solved the previous issue but have approached it from a different angle which is working now! I will potentially post again if I don't solve it.
I am using flask forms to do what I was trying.

Embeded pdf File is not displaying in Django

I was trying to display photos and pdf files in a django project using <embed> but pdf file is not displaying
Here is what i was doing
This is view function
#login_required
def view_documents(request):
students = Student.objects.filter(user=request.user)
return render(request, 'student/view_documents.html',{'students':students})
and then I used for tag in template
{% for student in students %}
#lines of code
{% endfor %}
and to display the pdf file i have used
<embed src="{{student.adhar_card_pdf.url}}" width="800px" height="400px" type="application/pdf"/>
but it was showing some kind of error like localhost refused to connect
i also used iframe
<iframe src="{{student.adhar_card_pdf.url}}" style="width:718px; height:700px;" frameborder="0"></iframe>
But image is displaying in the browser using same code without any error
<embed src="{{student.photo_jpg.url}}" width="230px" height="250px" />
Why pdf file is not displaying ?? Please help me
Thanx in advance.
Edited: In console it is showing -- Refused to display '' in a frame because it set 'X-Frame-Options' to 'deny'.
This is how it is displaying pdf
X_FRAME_OPTIONS = 'SAMEORIGIN'
Insert the above line in settings.py just before the MIDDLEWARE section
and for the file path in embed tag write path as
{{student.file.get.photo_jpg.url}}
And then give a hard reset in Chrome or any browser you are using.
It worked for me I hope it works for you as well.

Play a downloaded video with flask [duplicate]

This question already has an answer here:
Can't play HTML5 video using Flask
(1 answer)
Closed 7 years ago.
I have a simple flask server. I downloaded, using pafy, a video from a youtube link provided by the user.
#app.route('/')
def download():
return render_template('basic.html')
The basic.html template has a form that submits an action to download:
<form action="download_vid" method="post">
Link: <input type="text" name="download_path"><br>
<input type="submit" value="Submit">
</form>
I have another end point, /download_vid that looks like this.
#app.route('/download_vid', methods=['POST'])
def download_vid():
url = request.form['download_path']
v = pafy.new(url)
s = v.allstreams[len(v.allstreams)-1]
filename = s.download("static/test.mp4")
return redirect(url_for('done'))
The desired link is indeed downloaded as a .mp4 file in my static folder. I can watch it and I can also use it as a source for a tag in an HTML file, if I open it locally.
#app.route('/done')
def done():
return app.send_static_file('test.mp4')
From what I understand, 'send_static_file' serves files from the static directory. However, I get a 404 error when I run the server, even though the video is clearly there.
I have also tried a different version for done():
#app.route('/done')
def done():
return return render_template('vid.html')
Here, vid.html resides in templates and has a hard coded path to static/test.mp4. It is loaded after the download is complete. I do not have a 404 error in this case, but the tag don't do anything, it's just gray. If I open vid.html locally (double click on it), it works, it shows the video.
Can you please help me understand what is going on?
What I want to achieve is this:
Take an input from the user [ Done ]
Use that input to download a video [ Done ]
Serve that video back to the user [ ??? ]
I think you have something going on with file paths or file permissions.
Is the video being downloaded into static directory?
Is the static directory in the same directory, along with your main.py file?
Does your flask app have permissions to read the file?
I think the reason your file did not load in html template is because you referenced it as static/test.mp4 from an url - /done which translates the video path to be /done/static/test.mp4.
Instead of trying to push the file using Flask, you can redirect to the actual media file.
#app.route('/done')
def done():
return redirect('/static/test.mp4')

How to build an offline web app using Flask?

I'm prototyping an idea for a website that will use the HTML5 offline application cache for certain purposes. The website will be built with Python and Flask and that's where my main problem comes from: I'm working with those two for the first time, so I'm having a hard time getting the manifest file to work as expected.
The issue is that I'm getting 404's from the static files included in the manifest file. The manifest itself seems to be downloaded correctly, but the files that it points to are not. This is what is spit out in the console when loading the page:
Creating Application Cache with manifest http://127.0.0.1:5000/static/manifest.appcache offline-app:1
Application Cache Checking event offline-app:1
Application Cache Downloading event offline-app:1
Application Cache Progress event (0 of 2) http://127.0.0.1:5000/style.css offline-app:1
Application Cache Error event: Resource fetch failed (404) http://127.0.0.1:5000/style.css
The error is in the last line.
When the appcache fails even once, it stops the process completely and the offline cache doesn't work.
This is how my files are structured:
sandbox
offline-app
offline-app.py
static
manifest.appcache
script.js
style.css
templates
offline-app.html
This is the content of offline-app.py:
from flask import Flask, render_template
app = Flask(__name__)
#app.route('/offline-app')
def offline_app():
return render_template('offline-app.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=True)
This is what I have in offline-app.html:
<!DOCTYPE html>
<html manifest="{{ url_for('static', filename='manifest.appcache') }}">
<head>
<title>Offline App Sandbox - main page</title>
</head>
<body>
<h1>Welcome to the main page for the Offline App Sandbox!</h1>
<p>Some placeholder text</p>
</body>
</html>
This is my manifest.appcache file:
CACHE MANIFEST
/style.css
/script.js
I've tried having the manifest file in all different ways I could think of:
CACHE MANIFEST
/static/style.css
/static/script.js
or
CACHE MANIFEST
/offline-app/static/style.css
/offline-app/static/script.js
None of these worked. The same error was returned every time.
I'm certain the issue here is how the server is serving up the files listed in the manifest. Those files are probably being looked up in the wrong place, I guess. I either should place them somewhere else or I need something different in the cache manifest, but I have no idea what. I couldn't find anything online about having HTML5 offline applications with Flask.
Is anyone able to help me out?
I would have thought this one would work:
CACHE MANIFEST
/static/style.css
/static/script.js
But in any case, you should not hardcode the URLs for your static files. It's best to serve the manifest as a template (moved to the "templates" folder) so that you can use url_for to generate the path to the static files, something like this:
CACHE MANIFEST
{{ url_for('static', filename='style.css') }}
{{ url_for('static', filename='script.js') }}
Then in your HTML template you would have a reference to a route instead of a static file:
<html manifest="{{ url_for('manifest') }}">
And finally, you would add a new view function that returns the manifest:
from flask import make_response
#app.route('/manifest')
def manifest():
res = make_response(render_template('manifest.appcache'), 200)
res.headers["Content-Type"] = "text/cache-manifest"
return res

Categories