show images on the templates of django using google app engine - python

i am using google app engine with django to make a small application that it has these features
upload images ,
show images ,
minipulate images (rotate)
well after finishing part 1 , now i am somewhere stuck in part 2 where i need to show images.
i did everything i retrieved the image keys, but the images are not showing.
only the titles of the images i saved in the datastore.
here is my code:
<ul>
{% for image in image.all %}
<li>{{ image.title }} </li>
<li> <img src="/pictures/models.{{image.key}}"/> </li>
{% endfor %}
</ul>

Assuming
You uploaded the images to the blobstore
image.key is the blobstore key
You have a handler named BlobstoreImageHandler for /pictures/models\.(.*)/
Then you'd do something like
class BlobstoreImageHandler(blobstore.handler.BlobstoreDownloadHandler):
def get(self, resource):
resourse = str(urllib.unquote(resource))
blob_info = blobstore.BlobInfo.get(resource)
self.send_blob(blob_info)
which is straight out of http://code.google.com/appengine/docs/python/blobstore/overview.html#Serving_a_Blob

Related

Flask Serve PIL image in HTML from endpoint

I will preface by saying this is my first time working with flask & HTML to build a web app, so I may be using the wrong terminology in some places, apologies in advance.
I have used these two previous questions as reference for what i'm doing:
Flask render a word cloud
Passing a matplotlib figure to HTML (flask)
I am working a web app that allows a user to input a movie, and a wordcloud is returned.
The user starts on /search, where they input a movie name, I then redirect to /search_results where a list of movies with similar names are shown, the user selects the right film and submits. This part of the journey is all working fine, from here I take the movie name, I then apply a function I have built in python that creates a wordcloud based on this film name (in my code below this is what the function wordcloud_generator(1,session['search_value']) is doing in the fig route). The output of the wordcloud_generator() function is:
...
img = BytesIO()
wordcloud.to_image().save(img, 'PNG')
img.seek(0)
return img
I want to save this image to a route "/fig/<wordcloud_img>" and then be able to call it in the src of an img tag in the route "/images/<wordcloud_img>".
When running through this I get the error of at the point that I submit the movie name from /search_results and redirect to 'images'. Error: werkzeug.routing.BuildError: Could not build url for endpoint 'images'. Did you forget to specify values ['wordcloud_img']?
After this if I navigate manually to "localhost:5000/fig/wordcloud_img" then my function seems to run and the image is shown, and then if I manually navigate to "localhost:5000/images/wordcloud_img" the image is properly surfaced in the html.
It seems like I am doing this in the wrong order somehow and the function isn't running/generating the image before I try to access it on the /images source.
Routes
def search():
if request.method == 'POST':
movie_search = request.form['search_text']
session['returned_movies'], session['search_links'] = search_function(search_term = movie_search)
return redirect(url_for('search_result'))
return render_template('search.html',title='Search')
#app.route("/search_result", methods=['GET', 'POST'])
def search_result():
if request.method == 'POST':
movie = request.form['movie']
session['search_value'] = session['search_links'][session['returned_movies'].index(movie)]
return redirect(url_for('images'))
return render_template('search_results.html',title='Search Results')
#app.route("/images/<wordcloud_img>")
def images(wordcloud_img):
return render_template("wordcloud.html")
#app.route("/fig/<wordcloud_img>")
def fig(wordcloud_img):
img = wordcloud_generator(1,session['search_value'])
return send_file(img, mimetype='image/png')
wordcloud.html
{% extends "layout.html" %}
{% block content %}
<div>
{% if session['search_value'] %}
<p>Searching for a movie: {{ session['search_value'] }}</p>
{% else %}
<p>Oops, no movie selected </p>
{% endif %}
<body>
<img src="{{ url_for('fig', wordcloud_img = 'wordcloud_img') }}" alt="Image Placeholder" height="100">
</body>
</div>
{% endblock content %}
The problem is that you are not passing the image to the 'images' function that displays the template with the image. In your 'search_result' function, you will need to pass the wordcloud_image to the 'images' function like so:
return redirect(url_for('images'), wordcloud_img=your_image)
(replacing your_image with the actual image variable)
In your images route, you would then need to pass this received image to the template:
return render_template("wordcloud.html", wordcloud_img=wordcloud_img)
Then in your template, you can use this wordcloud_img variable like this:
<img src="{{ url_for('fig', wordcloud_img=wordcloud_img) }}" alt="Image Placeholder" height="100">

Django -- Dynamically showing Images that are created daily

What I want to accomplish is have an separate application generate graphs that will be placed in a directory of my Django project. Then in my template loop through and display all the graphs from that directory on the webpage. The generated graphs will be refreshed daily and will be of varying numbers depending on the day (so some days it could be 20 and/or the next it could be 50).
Option 1)
I don't think I want to use django manage.py collectstatic everyday. I've never gotten to the point of deploying a Django project to a server but my assumption is that I would have to collectstatic manually everyday on the server (which I could be thoroughly off on here)
Option 2)
I've tried creating a model Model Picture. The Char field is just my relative path to the picture. From there in my views I'm to rendering the path in the index(request) View Picture. From there in my template I'm trying to loop through the picture relative paths and show them Template Picture. When I remove photos = Photo.objects.all() & the {% for img in photos %} in the template the page does load Webpage working. However when I run it with all those parts in there I get a blank webpage with "what do you want to do with index" at the bottom. Webpage not working
Interested to hear if there are any better way of doing this . I'm not trying to user upload an image field because the amount of graphs will be substantial.
Details on Option 2:
---Notes---
Top Lvl Directory is--chartingtest-project
chartingtest is the project
sectors is the name of the app
media folder is a folder in the top level directory, not within the project or test folder
models.py in sectors app contains
class Photo(models.Model):
photoname = models.ImageField()
views.py in sectors app contains
from .models import Photo
def index(request):
pets = Pets.objects.all()
photos = Photo.objects.all()
return render(request, 'index.html', {'pets': pets}, {'photos': photos})
index.html template
{% load static %}
<H1>Hello World Index!</H1>
#Testing bringing in variables from a model (2020/05/07 Works!)
<ul>
{% for pet in pets %}
<li>{{pet.name}}</li>
{% endfor %}
</ul>
# ************************************
# This is where I'm trying display generated pictures from the media folder
# ************************************
<ul>
{% for img in photos %}
<li>
<img src="chart1s/{{img.image.url}}" />
</li>
{% endfor %}
</ul>
#Testing Static Image (2020/05/08 Works!)
<img src="{% static "OIP.jpg" %}"/>
<img src="{% static "temp_fig_00.png" %}"/>
settings.py in chartingtest project folder
#Media ROOT
MEDIA_ROOT = os.path.join(BASE_DIR, 'media/')
MEDIA_URL = '/media/'
You are correct that using static files will not work, by their name static files are not supposed to change.
The solution is to create a media folder and have your application save the graphs to that folder. Your model picture should point to that folder. Like you said, in your templates you can then iterate over that model to display all the graphs.
In production, you should create a cloud storage bucket and save your images there. Then make sure your settings.py directs any requests for images to your storage bucket.
Your picture model should use models.ImageField(), not a typical CharField, image = models.ImageField(). In your template as you iterate, you should call each image with <img src="{{ picture.image.url }}"
Apart from that, I would need to look in depth at the code to see what's going on, and I don't click links on stackoverflow posts. If you'd post the code in a comment might be able to take a closer link, but try those things first!

How to create a collage from Image urls in Python

I have a list of image urls (.jpg). I need to create a collage of all these images and I am looking for a python library that can do it.
I have explored the following libraries in depth but with no results:
1) https://pypi.python.org/pypi/collage/ - The best of the lot. Unfortunately, it takes a generic argument( for example, "The Avengers", "Mark Twain"), Google searches for images(need a token. Has limitations), and then outputs an Image collage. Will take a couple of days to fork the app into a library
2) https://github.com/fwenzel/collage - Creates an unattractive horizontal collage. Again need some forking
3) https://github.com/adrienverge/PhotoCollage - Application. No good.
Are there any libraries that directly take urls, download them and make a collage, or make a collage out of PIL image objects? I have checked out pretty much every library that Google search and SO has to show. I am desperately hoping there is some obscure library out there that can help my cause.
Thanks.
There is a Django package for this, very similar to your first option but with Django integration:
Django-Collage
If you have a set of images in your template, you can use it's filter to renderize them with:
{% load collage %}
{% load cache %}
{% cache 31536000 images view.id %}
{% get_collage for view.get_images as images %}
<div>
{% for image in images %}
<a href="{{ image.src }}" style="{{ image.css }}">
<img src="{{ image.url }}">
</a>
{% endfor %}
</div>
{% endcache %}
This code is taken from the tutorial provided in the package. I recommend you to check the official tutorial to learn how to use it.

Playing audio through audio tag in a Django application

How do i use the audio tag of html 5 to play a audio file that has been uploaded in a my django based application.
models.py - Link
settings.py - Link
In my templates i am using the audio tag in the following way -
{% for file in audio %}
<li>
<h4>{{ file.title }}</h4>
<div id="name">{{ file.name }}</div>
<div id="play"><audio src="{{ file.audio_file }}" controls="controls">
Your browser does not support the audio element.
</audio></div>
</li>
{% endfor %}
But I am not able to play the file.
Based on your settings, you cannot play the file because:
{{ file.audio_file }} returns value saved in the database, which is absolute path to media file, e.g. http://localhost:8000/Users/test/django_app/media/test.wav
To solve this, you need to:
Edit your models.py
class AudioFile(models.Model):
audio_file = models.FileField(upload_to="music")
upload_to -- A path that will be appended to your MEDIA_ROOT setting to determine the value of the url attribute
In your template, use {{ file.audio_file.url }} to correctly reference the URL of the uploaded file
You may need to delete existing files, because wrong path was saved in the database.

How to read images from directory, assemble them in <img src="">, and have flask return image?

I have a directory full of images. In one of my templates, I want to display these images
GET template:
render_template("registration.html", images=images)
in template: (using image/{{image}} because url_for doesn't accept variables)
{% for image in images %}
<input class="avatar" type = "radio" name = "avatar" value = "{{image}}"/><img src = "image/{{image}}"/>
{% endfor %}
and in app.py
#app.route('/images/<image>')
def images(image):
return send_file('public/assets/thumbs'+image, mimetype='image/jpg')
(public/assets/thumbs is the directory images reside in) however, this fails completely. Is there any tricks or hacks I can use to make this work?
I don't know if it could help you neither if the method i'll describe is good practice but to display images from directory (using send_from_directory in my view as described below by Andrew Allbright) in templates I was using :
{% for image in images %}
<img src="{{url_for('static', filename='image/')}}{{image}}"></img>
{% endfor %}
I remember I took inspiration from this SO post: Create dynamic URLs in Flask with url_for() (second answer) that indicates you can pass argument to url_for() in your templates.
Solution: send_from_directory()
#app.route("/image/<image>", methods=["GET"])
def image(image):
return send_from_directory(app.static_folder, 'assets/thumbs/' + image, mimetype='image/jpg')

Categories

Resources