Jinja2 Using images in HTML - python

I wasted a lot of time to find out what is wrong. I need your help now.
I want to render template with image from my filesystem. But it is not working.
Path - string that contains file name
#app.route('/', methods=['GET'])
def main():
return render_template('main.html',image = path)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>test</title>
</head>
<body>
<h2></h2>
<form method="post" enctype="multipart/form-data" action="/uploader">
<input type="file" name="file">
<button type="submit">Upload</button>
</form>
<img src={{ url_for('static', filename = image) }} >//i can't figure how to change this to use {{image}}
</body>
</html>

Just generate full image path in your view and pass it to your template
#app.route('/', methods=['GET'])
def main():
#path is filename string
image_file = url_for('static', filename=path)
return render_template('main.html', image_file=image_file)
and then just use it as full link
<img src={{ image_file}} >
if you have image file (with filename which stored in path) in your static folder this should work

If you was set the static folder like that (or other methods):
from flask import Flask
app = Flask(__name__, static_folder='static')
#app.route('/', methods=['GET'])
def main():
return render_template('main.html', image = url_for("static", filename=path))
or shorter:
return render_template('main.html', image='/static/' + path))
after you will put your image in /static folder you can get it from template:
<img src="{{image)}}">

I think something like this should work.
<img src="{{ url_for('static', filename='image') }}">
Where 'image' refers to the path of the image file inside static folder. Make sure to use the full name of image file along with its file type i.e. jpg, png etc.

Related

Is there a way to parse a file through to a <source> tag in HTML

I'm trying to make a private file host and I have it set to return a send_file() when the, for example, /media/someSong.mp3 url is called.
But I want to make it more styled so when you visit /media/someSong.mp3, instead of your browser trying to play that MP3 in it, it will use a HTML page with a tag that parses the send_file() sent by an argument.
Currently, I have this:
#app.route('/media/<mediaID>')
def mediaStuff(mediaID):
try:
return render_template('parse-it.html', title=title, media_file=send_file(f'./media/{mediaID}'))
# return send_file(f'./media/{mediaID}')
except FileNotFoundError:
return 'The media you tried to view doesn\'t exist.'
And here is what I have in my templates/parse-it.html file:
{% extends "base.html" %}
{% block content %}
<h1>You are now viewing ...!</h1>
<source src={{media_file}}>
{% endblock %}
However all I see is <Response 200 OK> or something like that. No file to be seen!
Would I use a get_file() and then return Response(getfileVar) in that media_file argument?
send_file returns a Response object. It makes no sense to pass this to the template.
So you need two endpoints. One to display your website containing the media element and one to stream the file from the directory. I recommend using send_from_directory for this.
This is a simple example that lists all files within a directory and offers them for playback or viewing. The distinction is made based on the mime type of the file. This is determined via guess_type.
The exmpale uses the instance path to ensure separation of files and application.
import os
from flask import (
Flask,
render_template,
send_from_directory
)
from mimetypes import guess_type
app = Flask(__name__)
app.config['MEDIA_FOLDER'] = os.path.join(app.instance_path, 'media')
try:
os.makedirs(app.config['MEDIA_FOLDER'])
except:
pass
def listfiles(target):
for filename in os.listdir(target):
mimetype = guess_type(os.path.join(target, filename))
yield (
filename,
mimetype,
)
#app.route('/')
def index():
files = listfiles(app.config['MEDIA_FOLDER'])
return render_template('index.html', **locals())
#app.route('/media/<path:filename>')
def media(filename):
return send_from_directory(
app.config['MEDIA_FOLDER'],
filename
)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
{% for filename, type in files -%}
<div>
{% set mimetype, encoding = type -%}
{% if mimetype.startswith('audio') -%}
<audio controls>
<source src="{{ url_for('media', filename=filename) }}" type="{{ mimetype }}">
</audio>
{% elif mimetype.startswith('image') -%}
<img src="{{ url_for('media', filename=filename) }}" />
{% endif -%}
</div>
{% endfor -%}
</body>
</html>

python Unsupported method ('POST')

python Unsupported method ('POST') this program is meant to convert images to text but I kept getting this error over and over I don't know what is the problem
I don't know exactly if the problem with the HTML code or this code
or am I missing other files
I don't quite understand the HTML code so I will be thankful if you elaborate
from gettext import gettext
from click import get_text_stream
from flask import Flask, render_template, request
import os, pytesseract
from jinja2 import Template
from flask_uploads import UploadSet, configure_uploads, IMAGES
from PIL import Image
project_dir = os.path.dirname(os.path.abspath(__file__))
app = Flask(__name__, static_url_path='', static_folder = 'static', template_folder = 'gg.html')
photos = UploadSet('photos', IMAGES)
app.config['DEBUG'] = True
app.config['UPLOAD_FOLDER'] = 'images'
class UploadText(object):
def __init__(self, file):
self_file = pytesseract.image_to_string(Image.open(project_dir + '/imges/' + file))
#app.route('/gg', methods =["POST" , "GET"])
def home():
if request.method == "POST":
if 'photo' not in request.files:
return 'there is no photo in form'
name = request.form['img-name'] + '.jpg'
photo = request.files['photo']
path = os.path.join(app.config['UPLOAD_FOLDER'], name)
photo.save(path)
textObject = get_text_stream(name)
return textObject.file
return render_template('gg.html')
if __name__ == ' __main__':
app.run()
The HTML:
<head>
<meta charset = "utf-8">
<title> Image to Text</title>
</head>
<body>
<div class='text-center'><br><br>
<form method='post' enctype="multipart/form-data">
<input type="file" class='btn btn-dark' name='photo'>
<input id ='input' type='text' class ='form-control' placeholder='enter image name' name='img-name'>
<input class = 'btn btn-dark' type='submit'>
</form>
</div>
</body>
<style>
#input{
margin: auto;
width: auto;
}
</style>
You don't specify an action attribute in the HTML <form> tag, which tells the form where to submit to. Instead try:
<form method='post' action='/gg' enctype="multipart/form-data">
Of course it's also possible to render the /gg part dynamically, based on the name of your python function home:
<form method='post' action='{{ url_for("home") }}' enctype="multipart/form-data">

Flask mp4 file not being displayed in video tag using file path

I have a flask application that stores mp4 files in a local directory and save the path in my db. I'm able to access the file user send_file provided by flask and download but when I pass the path to the video tag, it's not being displayed. See code below:
Saving the video file: works fine as expected
#app.route('/', methods=['GET', 'POST'])
def index():
form = VideoPicForm()
if form.validate_on_submit():
if form.vid.name not in request.files:
flash('No video part specified')
return redirect(url_for('index'))
file = request.files[form.vid.name]
if file.filename == '':
flash('No file selected for uploading')
return redirect(url_for('index'))
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
filepath = os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename)
file.save(filepath)
video= VideosFiles(description=form.description.data, vidpath=filepath)
db.session.add(video)
db.session.commit()
flash('video uploaded successfully...')
return redirect(url_for('index'))
return render_template('index.html', title='Home', form=form)
Accessing from template: ```file not rendering``
#app.route('/display')
def display():
file_data= VideosFiles.query.filter_by(id=1).first()
video= file_data.vidpath
return render_template('display.html', title='Videos', video=video)
In template:
<video width="320" height="240" controls>
<source src="{{video}}" type="video/mp4" />
</video>
But when I download using send_file, the video is immediatly downloaded:
#app.route('/download')
def download():
file_data= VideosFiles.query.filter_by(id=1).first()
video= file_data.vidpath
return send_file(video, as_attachment=True)
I'm I missing anything that's causing the video not being rendered in template?
There is a small change in your code. make sure your video store in static folder in flask app structure.
I have the same issue as you, when I store the video in static folder then it's working fine.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<video width="400" controls>
<source src="{{ url_for('static', filename='small.mp4') }}" type="video/mp4">
</video>
</body>
</html>
And also please use the url_for for html render.

Flask renaming uploaded file

in my app i am uploading images to a folder but i cannot figure out how to rename them from the form to something
this is my .py
import os
from flask import Flask, render_template, request
app = Flask(__name__)
APP_ROOT = os.path.dirname(os.path.abspath(__file__))
#app.route("/")
def index():
return render_template("upload.html")
#app.route("/upload", methods=['GET','POST'])
def upload():
target = os.path.join(APP_ROOT, 'images/')
print(target)
if not os.path.isdir(target):
os.mkdir(target)
for file in request.files.getlist("file"):
print(file)
filename = file.filename
destination = "/".join([target, filename])
print(destination)
file.save(destination)
return render_template("complete.html")
if __name__ == "__main__":
app.run(port=4555, debug=True)
this is my .html
obviously the input type="text" isn't working for me
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>Upload here</h1>
<form id="upload-form" action="{{url_for('upload')}}" method="POST" enctype="multipart/form-data">
<input type="file" name="file" accept="image/*" multiple></br>
New name for image<input type="text">
<input type="submit" value="send">
</form>
</body>
</html>
for file in request.files.getlist("file"):
print(file)
filename = file.filename
destination = "/".join([target, filename])
print(destination)
file.save(destination)
Here you set the destination for the file which includes the new filename. You set filename to file.filename - essentially you are saying to keep the filename.
To rename the file you can overwrite the filename like so:
filename = "myfile.jpg"
This could be dynamic, eg:
# keep extension for later
extension = filename.split()[-1]
current_dt = datetime.datetime(
new_filename = "upload-{}.{}".format(
time.time(), extension
)
This would save the file as something like: 1574685161.690482.jpg

attach img file in pdf weasyprint

I need help with attaching img file in pdfs. We use the WeasyPrint lib for generating pdf from html.
in html connect img file like this
<img src="1.png" alt="">
<img src="2.png" alt="">
<img src="3.png" alt="">
but it is not working. I don't see the image.
use static for path of the image file
{% load static %}
<img src="{% static 'images/static.jpg' %}" alt="">
and pass base_url in HTML class in views.py
pdf_file = HTML(string=rendered_html, base_url=request.build_absolute_uri())
html file
<!DOCTYPE html>
<html lang="en">
{% load static %}
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div>
<img src="{% static 'images/static.jpg' %}" alt="">
</div>
</body>
</html>
views.py
from django.template.loader import get_template
from weasyprint import HTML, CSS
from django.conf import settings
from django.http import HttpResponse
def generate_pdf(request):
html_template = get_template('latest/html_pdf.html')
user = request.user
rendered_html = html_template.render().encode(encoding="UTF-8")
pdf_file = HTML(string=rendered_html, base_url=request.build_absolute_uri()).write_pdf(stylesheets=[CSS(settings.STATIC_ROOT + '/css/generate_html.css')])
http_response = HttpResponse(pdf_file, content_type='application/pdf')
http_response['Content-Disposition'] = 'filename="generate_html.pdf"'
return http_response
In case of sending emails with pdf attached, it's possible to pass path from view to function dedicated to emails.
views.py
[...]
path = request.build_absolute_uri() # build absolute path
order_confirmation.delay(order.id, path) # pass to func
[...]
tasks.py
#app.task
def order_confirmation(order_id, path): # receive path
order = Order.objects.get(id=order_id)
subject = f"Order nr. {order.id}"
email_from = settings.EMAIL
email_to = order.get_email
message = (...)
email = EmailMessage(subject, message, email_from, [email_to])
html = render_to_string('pdf.html', {'order' : order, 'company': company})
out = BytesIO()
stylesheets=[weasyprint.CSS(settings.STATIC_ROOT + '/css/pdf.css')]
weasyprint.HTML(string=html, base_url=path).write_pdf(out, stylesheets=stylesheets) # use here
email.attach(f'order_{order.id}.pdf',
out.getvalue(),
'application/pdf')
email.send()

Categories