How to change image path dynamically with Flask - html

Hi is there a way to dynamically load different images whenever I get into my flask app?
I've got 10 images each is named 'accueil_X' with X is 0,1,2,...
app.py
#app.route('/', methods=("POST", "GET"))
def home():
random = randrange(10)
random_pix = 'accueil_'+str(random)+'.png'
HTML
<img src="{{url_for('static', filename='+{{ random_pix }}+')}}" width=100%, alt="">
Jinja seems to load an image named +{{ random_pix }}+: How can I fix this ? thank you

so you want to load a random image with each refresh of the home page:
#app.route('/', methods=("POST", "GET"))
def home():
random = randrange(10)
random_pix = 'accueil_'+str(random)+'.png'
[..]
# i added this missing line to get code more clear
return render_template('home.html', random_pix=random_pix)
Jinja seems to load an image named +{{ random_pix }}+: How can I fix this ?
it's simple, just remove the {{ }} surrounding the variable random_pix
<img src="{{ url_for('static', filename='\'' + random_pix + '\'') }}" width=100%, alt="">
jinja2 uses {{ .. }} to evaluate any valid expression
refer to this doc

You could do this with a context processor which is the equivelant of Django's "template tag".
This can be used to pass a number of variables to all templates, or pass a function which can then be called in all templates.
First import the required modules, and initialise the app:
from flask import Flask, url_for, render_template
from random import randrange
app = Flask(__name__)
Then define a context processor:
#app.context_processor
def utility_processor():
def random_image():
number = randrange(10)
f = 'accueil_' + str(number) + '.png'
return url_for('static', filename=f)
return dict(rand_im=random_image)
Notice you've passed the random_image function which can then be called in the template as rand_im. Instead of putting the call to url_for in the template, you've done this in Python.
So you could render this with the following in any template:
<img src="{{ rand_im() }}" width="100%" />

Related

How can I display PIL image to html with render_template flask?

I tried to display my edited image with PIL package, when I tried to make it to display on the html <img src=''></img> it doesn't appear anything, but I see the file name on inspect elements was <img src="<_io.BytesIO object at 0x000001EDA8F76E00>">. How do I make the edited image display properly?
app.py
#app.route("/api/games/shipper/image/", methods=["GET"])
def games_shipper():
... # My stuff up here
image_io = BytesIO()
img.save(image_io, "PNG")
image_io.seek(0)
return render_template('image.html', image_data=image_io)
image.html
... // My stuff up here
<body>
<center>
<image src="{{ image_data }}"></image>
</center>
</body>
You can read the data from the buffer with the getvalue() function and then convert it. The base64 encoded data can then be passed to the src parameter as a data url.
from base64 import b64encode
#app.route("/api/games/shipper/image/", methods=["GET"])
def games_shipper():
... # My stuff up here
image_io = BytesIO()
img.save(image_io, 'PNG')
dataurl = 'data:image/png;base64,' + b64encode(image_io.getvalue()).decode('ascii')
return render_template('image.html', image_data=dataurl)
If you pass the image as a dataurl, there is no way to shrink the string. However, there is the possibility of serving the file as pure image data. You can use send_file in another endpoint for this. You serve the page (template) in one endpoint and the image file in a second.
from flask import send_file
#app.route('/')
def index():
return render_template('index.html')
#app.route('/image')
def game_shipper():
# ...
image_io = io.BytesIO()
img.save(image_io, format='PNG')
image_io.seek(0)
return send_file(
image_io,
as_attachment=False,
mimetype='image/png'
)
<body>
<center>
<img src="{{ url_for('game_shipper') }}" />
</center>
</body>
You'll need to encode your image in Base64 to display it in the img tag directly, see e.g. How to display Base64 images in HTML
The traditional way to display images in Flask templates is to save the image in Flask's static folder and link to it in your template like so
<body>
<center>
<image src="/static/{{image_name}}.png"></image>
</center>
</body>

Image not showing up in the browser

Here's what Im trying to do.. The images I save on the database are going to the correct path. But they don't show up in the site.
#blogs.route("/post/new", methods=['GET', 'POST'])
def new_post():
if ('user' in session and session['user'] == params["username"]):
form = PostForm()
if form.validate_on_submit():
pic = save_picture(request.files['pic'])
post = Post(title=form.title.data,
content=form.content.data, img=pic)
db.session.add(post)
db.session.commit()
flash('Your post has been created!', 'success')
image_file = url_for('static', filename = 'profile_pics/' + pic)
return render_template('post.html',image_file=image_file)
return render_template('create_post.html', title='New Post',
form=form)
return "please login to the dashboard first. Dont try to enter without logging in!"
The HTML side
<img src="{{image_file}}" alt="error">
Found a fix!!
I figured out that one can use the set keyword from python as a variable to store the post.img in it and then refer it inside the source.
{% set img_name = 'profile_pics/' + post.img %}
<img src="{{url_for('static', filename = img_name)}}" alt="error">
This would be the route function:
image_file = url_for('static', filename='profile_pics/' + post.img)
return render_template('template.html', image_file=image_file)
and this is what it looks like in the template:
<img src="{{ image_file }}">
The issue is probably that You are not really able to have nested variables inside html especially because jinja probably interpreted that as a literal string

Django, set img src dynamically

Before someone marks this as duplicate I have read and tried solutions in these threads:
Use Django Template Tags in img src
django 1.5 - How to use variables inside static tag
Django: Insert image in a template whose path is dynamic
And still have not been able to get it to work.
So I'm using Django built in UpdateView to update an data base entry and I'm trying to load image to template where part of src is dynamic like this:
edit_journal_entry_form.html
{% extends 'base.html' %}
{% load staticfiles%}
<form method="post">
{% csrf_token %}
{% static "" as baseUrl %}
<img src="{{ baseUrl }}/lpr_images/{{journalEntry.license_plate_nr_img}}"></img>
<img src="{% static "" %}/lpr_images/{{journalEntry.license_plate_nr_img}}" />
<img id="edit_img" src="{% static 'lpr_images/' %}{{journalEntry.license_plate_nr_img}}" alt="Image not read!"/>
{{ form.as_p }}
<button class="btn btn-success" type="submit">Submit</button>
...
views.py
class JournalEntryUpdate(UpdateView):
model = JournalEntry
template_name = 'gate_operator/edit_journal_entry_form.html'
success_url = '/gate_operator/journal/'
fields = [
'license_plate_nr',
'license_plate_nr_img',
...
]
def form_valid(self, form):
object = form.save(commit=False)
object.user = self.request.user
object.save()
return super(JournalEntryUpdate, self).form_valid(form)
models.py
class JournalEntry(models.Model):
license_plate_nr = models.CharField(max_length=20, blank=True)
license_plate_nr_img = models.CharField(max_length=100, blank=True)
...
None of this works in console I can se that I'm getting only the static part: GET http://127.0.0.1:8000/static//lpr_images/ 404 (Not Found)
I tried to hard code the url just to make sure I'm on the right path, so this successfully shows image: http://127.0.0.1:8000/static//lpr_images/2018_04_26_08_43_25.png
So what am I missing here or doing wrong?
In the template, you should use journalentry (all lowercase), instead of journalEntry.

Django 1.11 How to display template variable from within HTML saved in model for CMS Site

Within a template, I need to render a {{ variable }} from HTML content saved in a model instance.
Below are the stripped down parts of the code.
page.html
{% load static %}
<html>
<head>
<styles, links, etc.>
<title>{{ object.title }}</title>
</head>
<body>
<div>{{ object.html_content }}</div>
</body>
</html>
Model
class Page(models.Model):
title = models.CharField(max_length=30)
html_content = models.TextField()
GlobalMixin
# Used site wide for Global information.
class GlobalMixin(object):
def get_context_data(self, *args, **kwargs):
context = super(GlobalMixin, self).get_context_data(*args, **kwargs)
context['variable'] = "A Global piece of information"
return context
View
from .mixins import GlobalMixin
from .models import Page
PageView(GlobalMixin, generic.DetailView):
model = Page
template_name = "my_app/page.html"
def get_context_data(self, *args, **kwargs):
context = super(PageView, self).get_context_data(*args, **kwargs)
return context
Admin & HTML Content Field
I then enter admin, add new Page, enter my HTML content into html_content Field "Html Content" as per the following example.
<p>This is {{ variable }} that I need to display within my rendered page!</p>
Then SAVE.
BROWSER RESULTS
This is {{ variable }} that I need to display within my loaded page!
I know there is Django Flat Pages, but it doesn't look like it works for me as I require Global variables in my templates that flat pages doesn't offer.
The template is being rendered directly with the models content without looking at it.
I think I need to process the html_content field in the view and then add the required context variables to the context returned or save a temporary template file, append the html_content into the file, then render it.
How do I do make this work?
Is there a Django packaged interface that I can use to process the template from within my view?
I worked it out. Here's the code if anyone else comes across this or has a better way, please share.
Change View type to TemplateView, use slug in url to get model instance, use django.template.engines to convert the string to a template object then render the template object and return it in the context.
page.html
{% load static %}
<html>
<head>
<styles, links, etc.>
<title>{{ object.title }}</title>
</head>
<body>
<!-- <div>{{ object.html_content }}</div> -->
<div>{{ html_content }}</div>
</body>
</html>
views.py
from django.views.generic.base import TemplateView
from .mixins import GlobalMixin
from .models import Page
# NEW
from django.shortcuts import get_object_or_404
from django.template import engines
PageView(GlobalMixin, TemplateView): # generic.DetailView
# model = Page
template_name = "my_app/page.html"
def get_context_data(self, *args, **kwargs):
context = super(PageView, self).get_context_data(*args, **kwargs)
# NEW
context['object'] = get_object_or_404(Page, slug=self.kwargs['slug'])
t = engines['django'].from_string(context['object'].html_content)
context['html_content'] = t.render(context=context, request=None)
return context
I thought you could use custom filter like below.
file path
yourapp/templatetags/__init__.py
yourapp/templatetags/filters.py
filters.py
from django import template
import re
register = template.Library()
#register.filter(name="change_global_variable")
def change_global_variable(value):
return re.sub(r'\{\{(.*)\}\}', 'A global piece', value)
template
{% load static %}
{% load filters %} //filters.py//
<html>
<head>
<styles, links, etc.>
<title>{{ object.title }}</title>
</head>
<body>
<div>{{ object.html_content | change_global_variable}}</div>
</body>
</html>

How to output just html image tag when I have text and html in django template output?

I am using this to output,
{{ movie.img }}
and I get the output is supposed to be something like,
u'<img src="//upload.wikimedia.org/wikipedia/en/thumb/8/8a/Dark_Knight.jpg/220px-Dark_Knight.jpg" alt="" height="327" width="220" >\nTheatrical release poster'
How do I just output the html image part? I don't want the Theatrical release poster to appear in the output.
Since you are getting that as just text, your best solution would be to write a template filter that would strip content not in the <img> html tag.
If the object were a ImageField (or FileField), you can call on the url attribute only, {{ movie.img.url }}
update
Ok, here's a basic, probably too naive template filter for your use.
from django import template
from django.template.defaultfilters import stringfilter
import re
register = template.Library()
#register.filter(is_safe=True)
#stringfilter
def get_img_tag(value):
result = re.search("<.*?>", value)
if result:
return result.group()
return value
Use:
{{ movie.img|get_img_tag|safe }}