I am following this video to create an image gallery using flask and python https://www.youtube.com/watch?v=yO_XNCsBIsg&t=636s
I these github files for (coppied the #app.route('/gallery')) app.py and gallery.html and ran the exact code but I am getting an error:
werkzeug.routing.BuildError: Could not build url for endpoint 'send_image' with values ['filename']. Did you mean 'index' instead?
Here is my exact code
main.py
#!/usr/bin/env python
from flask import Flask, request, send_from_directory, flash, redirect, render_template, request, url_for,jsonify
#https://stackoverflow.com/questions/32019733/getting-value-from-select-tag-using-flask
# reference to code is from https://pythonprogramming.net/jquery-flask-tutorial/
# and from https://www.blog.pythonlibrary.org/2017/12/13/flask-101-how-to-add-a-search-form/
app = Flask(__name__)
# this runs in the background for registering the compnay link that was put in
#app.route('/background_process')
def background_process():
lang = request.args.get('proglang', 0, type=str)
#just checking what was typed, this will be put into a python code eventrually
return jsonify(result=lang)
#app.route('/')
def index():
return render_template('interactive.html', data=[{'name':'red'}, {'name':'green'}, {'name':'blue'}])
filename = request.args.get('proglang')
#app.route("/black" , methods=['GET', 'POST'])
def black():
select = request.form.get('comp_select')
if select=="blue":
return(str("hi")) # just to see what select is
else:
return(str("bye"))
import os
#app.route('/gallery')
def get_gallery():
image_names = os.listdir('./images')
print(image_names)
return render_template("gallery.html", image_names=image_names)
if __name__=='__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
gallery.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">Thumbnail Gallery</h1>
</div>
{{image_names}}
<hr>
{% for image_name in image_names %}
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<img class="img-responsive" src=" {{url_for('send_image', filename=image_name)}}">
</div>
{% endfor %}
</div>
</div>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous"></script>
</body>
</html>
I'm leaving out my other html files because they aren't needed for my testing of the gallery route.
You are missing the "send_image" route in your Python code:
#app.route('/upload/<filename>')
def send_image(filename):
return send_from_directory("images", filename)
Related
I would like to send image with Flask app when I click to predict button in my html code.
Code is supposed to get prompt and run ML model and generate image based on input prompt. I can generate the picture but somehow I can not send it to html or html doesn't show the image.
Anyone can check my flask and html code where the problem is ? My flask image send method is wrong or html part is wrong ? How to show the image in html ?
import os
import io
import base64
from PIL import Image
import torch
from torch import autocast
from diffusers import StableDiffusionPipeline, LMSDiscreteScheduler
import transformers
from flask import Flask, render_template, request
app = Flask(__name__)
lms = LMSDiscreteScheduler(
beta_start=0.00085,
beta_end=0.012,
beta_schedule="scaled_linear"
)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
pipe = StableDiffusionPipeline.from_pretrained(
"CompVis/stable-diffusion-v1-4",
scheduler=lms,
use_auth_token=True,
cache_dir=os.getenv("cache_dir", "./models")
).to("cuda")
#app.route('/', methods=['GET'])
def page_template():
return render_template('index.html')
#app.route('/', methods=['POST'])
def predict():
prompt_text = request.form['word']
with autocast("cuda"):
image = pipe(prompt_text)["sample"][0]
data = io.BytesIO()
image.save(data, "JPEG")
encoded_img_data = base64.b64encode(data.getvalue())
return render_template("index.html", img_data=encoded_img_data.decode('utf-8'))
if __name__ == '__main__':
app.run()
<!DOCTYPE html>
<html>
<head>
<title>Tutorial</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
</head>
<body>
<h1 class="text-center">Stable Diffusion</h1>
<form class="p-3 text-center" action='/', method="post" enctype="multipart/form-data" >
<label for="promptfield" class="form-label">StableDiffusionPrompt</label>
<input type="text" class="form-control" id="promptfield" name="word" placeholder="Please enter your prompt" />
<input class="form-control" type="file" name="imagefile" >
<input class="btn btn-primary mt-3" type="submit" value="Predict Image" >
</form>
{% if prediction %}
<img id="picture" src="data:image/jpeg;base64,{{ img_data }}">
<p> img id="picture" src="data:image/jpeg;base64,{{ img_data }}"</p>
{% endif %}
</body>
</html>
here is the output of encoded_img_data.decode('utf-8').
So, I have an image classification app that is meant to display an uploaded image along with the prediction or class. I have two template files: index.html and results.html. The flask app is meant to render the result.html when a post request is made, however, it only displays the alt text.
Below is my flask app:
app = Flask(__name__)
UPLOAD_FOLDER = 'static/uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def index():
return render_template('index.html')
#app.route('/', methods=['POST'])
def upload_file():
if request.method == 'POST':
if 'file' not in request.files:
return redirect(request.url)
file = request.files.get('file')
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if not file:
return
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
img_bytes = file.read()
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
#image_url = url_for('uploaded_file', filename=filename)
class_id, class_name, score = get_prediction(input_img= img_bytes)
return render_template('result.html', class_id=class_id, class_name=class_name, score=score, filename=filename)
#app.route('/display/<filename>')
def display_image(filename):
return redirect(url_for('static', filename='uploads/' + filename), code=301)
In my template file i.e. results.html, I have the following code to display the uploaded image alongside the prediction but it only shows the prediction without an image:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="//stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">
<style>
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
}
#media (min-width: 768px) {
.bd-placeholder-img-lg {
font-size: 3.5rem;
}
}
</style>
<link rel="stylesheet" href="/static/style.css">
<title>Prediction using ResNet</title>
</head>
<body class="text-center">
<form class="form-signin" method=post enctype=multipart/form-data>
<img class="mb-4" src="{{ url_for('display_image', filename=filename) }}" alt="no image found" width="300" height="300">
<h1 class="h3 mb-3 font-weight-normal">Results</h1>
<h5 class="h5 mb-3 font-weight-normal">Prediction: {{ '{} ({:.4f})'.format(class_name, score) }}</h5>
<h5 class="h6 mb-3 font-weight-normal">Prediction ID: {{ class_id }}</h5>
<p class="mt-5 mb-3 text-muted">Built using Pytorch, Flask and Joy</p>
</form>
<script src="//code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.6/umd/popper.min.js" integrity="sha384-wHAiFfRlMFy6i5SRaxvfOCifBUQy1xHdJ/yoi7FRNXMRBu5WHdZYu1hA6ZOblgut" crossorigin="anonymous"></script>
<script src="//stackpath.bootstrapcdn.com/bootstrap/4.2.1/js/bootstrap.min.js" integrity="sha384-B0UglyR+jN6CkvvICOB2joaf5I4l3gm9GU6Hc1og6Ls7i6U/mkkaduKaBhlAXv9k" crossorigin="anonymous"></script>
</body>
</html>
This displays the alt text i.e no image found. Kindly assist with suggestions. Thanks.
My template is as follows:
<!-- template1.html -->
<html>
<head>
<title>Item Details</title>
</head>
<body>
<p>{{ req }}</p>
</body>
</html>
To render the template I am using the following code:
from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
app = FastAPI()
template = Jinja2Templates(directory="templates")
#app.get("/list_items")
def home(request: Request):
return template.TemplateResponse('template1.html',{"req": req})
#app.get("/", response_class=HTMLResponse)
async def read_items():
return """
<html>
<head>
<title></title>
</head>
<body>
<form action="/list_items">
<input type="text" placeholder="Search.." name="search">
<button type="submit">Search</button>
</form>
</body>
</html>
"""
But I do not want to use a separate folder with files for a simple template. How do I pass the html text instead of the function TemplateResponse
You can use HTMLResponse. Pass HTMLResponse as the parameter response_class of your route.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items", response_class=HTMLResponse)
def read_items():
return """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
You can also override the response directly in your endpoint, by returning it.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items")
def read_items():
html_content = """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
Update
Jinja2Templates.TemplateResponse expects as name parameter a filename that is pointing to the template your would like to return, and which lies in the Jinja2Templates directory you defined (e.g., Jinja2Templates(directory="templates") ). You can't pass the template contents to its place. Jinja2Templates will attempt to retrieve the file you passed using the directory you defined earlier, see here -> here -> here. Hence, what you are asking, it doesn't seem to be natively possible (but, with some hackish stuff maybe doable); however, there is nothing wrong with having a templates directory, even for small template files.
registration and login page is working properly but mine count of likes is not showing in django... I don't know why... Can somebody help me to find this error... It will be the great help... Thank You!!
1.Views.py
from django.shortcuts import render, get_object_or_404, redirect
from datasecurity.models import Post
from django.urls import reverse
from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
# Create your views here.
#login_required
def likes(request, pk):
post=get_object_or_404(Post, pk=pk)
post.likes.add(request.user)
return HttpResponseRedirect(reverse('datasecurity:datasecurity'))
def datasecurity(request):
allPosts= Post.objects.all()
context={'allPosts': allPosts}
def __init__(self, *args, **kwargs):
stuff = get_object_or_404(Post, id = self.kwargs['pk'])
total_likes = stuff.total_likes()
context['total_likes'] = total_likes
return render(request, 'datasecurity/data.html',context=context)
def blogHome(request, slug):
post=Post.objects.filter(slug=slug).first()
context={"post":post}
return render(request, "datasecurity/blogHome.html", context)
2.Urls.py
from django.conf.urls import url
from . import views
app_name = 'datasecurity'
urlpatterns = [
url(r'^$', views.datasecurity, name="datasecurity"),
url(r'^datasecurity/(?P<slug>[^/]+)', views.blogHome, name='blogHome'),
url(r'^likes/(?P<pk>\d+)/', views.likes, name = "likes"),
]
3.models.py
from django.db import models
from ckeditor.fields import RichTextField
from django.contrib.auth.models import User
# Create your models here.
class Post(models.Model):
sno=models.AutoField(primary_key=True)
title=models.CharField(max_length=255)
author=models.CharField(max_length=14)
slug=models.CharField(max_length=130)
timeStamp=models.DateTimeField(blank=True)
content=RichTextField(blank=True, null=True)
img = models.ImageField(blank=True, null=True, upload_to="dataimage/")
likes = models.ManyToManyField(User)
#property
def total_likes(self):
return self.likes.count()
def __str__(self):
return self.title + " by " + self.author
4.data.html
<!DOCTYPE html>
{% load static %}
<html lang="en" dir="ltr">
<head>
<meta
name="viewport"
content="width=device-width, initial-scale=1, shrink-to-fit=no"
/>
<link
href="https://fonts.googleapis.com/css?family=Lato:100,300,400,700,900"
rel="stylesheet"
/>
<meta charset="utf-8">
<title></title>
<!-- Bootstrap core CSS -->
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
<link rel="stylesheet" href="{% static 'css/datasecurity.css' %}">
<link rel="preconnect" href="https://fonts.gstatic.com">
<link href="https://fonts.googleapis.com/css2?family=PT+Sans&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Bebas+Neue&family=PT+Sans&display=swap" rel="stylesheet">
<link rel="canonical" href="https://getbootstrap.com/docs/5.0/examples/cover/">
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v9.0" nonce="noEcH88O"></script>
<script async defer crossorigin="anonymous" src="https://connect.facebook.net/en_GB/sdk.js#xfbml=1&version=v3.2"></script>
</head>
<body>
<!-- End header -->
<div id="page-wraper">
<!-- Sidebar Menu -->
<div class="responsive-nav">
<div class="top-navbar">
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container">
<marquee><ul class="navbar-nav ml-auto">
<li class="nav-item"><a class="nav-link" href="{% url 'careforallapp:base' %}">Home</a></li>
</ul></marquee>
</div>
</div>
</nav>
</div>
<section class="section about-me" data-section="section1">
<div class="container">
<div class="section-heading">
<h2>Welcome to Data Security</h2>
{% for post in allPosts %}
<div class="line-dec"></div>
<span
>This is a Bootstrap v4.2.1 CSS Template for you. Edit and use
this layout for your site. Updated on 21 May 2019 for repeated main menu HTML code.</span
>
</div>
<div class="left-image-post">
<div class="row">
<div class="col-md-6">
<div class="left-image">
{% if post.img %}
<img src="{{ post.img.url }}" alt="" />
{% endif %}
</div>
</div>
<div class="col-md-6">
<div class="right-text">
<h4>{{post.title}}</h4>
<h6>Article by {{post.author}}</h6>
<h2>{{post.datetime}}</h2>
<p>
{{post.content|safe | truncatechars:280}}
</p>
<form action = "{% url 'datasecurity:likes' pk=post.pk %}" method = "POST">
{% csrf_token %}
<button type="submit" name="post_id" value = "post_id" class="btn"> Like </button> - {{ total_likes }} likes
</form><br><br>
<div class="white-button">
Read More
</div><br>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</div>
{% endfor %}
</div>
<div>
</section>
</div>
There is no error when I debug the code .. may be it is logical error .. I really don't know .. can someone help me to find out the error Thank you
Looks like you want to display all posts in your datasecurity view. You have declared a function __init__ inside it for some reason (not even using it, also it's not even in a class as __init__ might imply). Change the view like this:
def datasecurity(request):
allPosts= Post.objects.all()
context={'allPosts': allPosts}
return render(request, 'datasecurity/data.html',context=context)
Now in your template you are using {{ total_likes }} but you haven't passed any such variable in the context. But I notice you have declared a method on your model that does the same so change it to {{ post.total_likes }}.
Problem: My Bokeh plot, implemented with Flask, is not showing in my browser. When I run the app, the Bokeh frame (with the tools), as well as the x-axis label show up, but no data is plotted inside.
Already tried: I've made sure that the Bokeh version mentioned in the HTML files is as others have suggested. I'm pretty sure I've exhausted the SO solutions presented already. I've used print statements throughout the program and determined that the data is actually collected, cleaned, and processed with the components module and passed to 'script'. So therefore, as far as I can tell, the code seems to be stuck at the 'last render_template line?
from flask import Flask, render_template, request, redirect, session
import pandas as pd
import quandl
from bokeh.plotting import figure, output_file, save
from bokeh.embed import components
from bokeh.io import show
app = Flask(__name__) #create an instance of the flask class (named 'app') in the current file
app.vars={}
#app.route('/')
def main():
return redirect('/index')
#app.route('/index', methods=['GET'])
def index():
return render_template('index.html')
#app.route('/plot', methods=['POST'])
def plot():
app.vars['current_symbol'] = request.form['current_symbol']
quandl.ApiConfig.api_key = 'CD38JS9JqAdmdeio9JPW'
req_data = quandl.get_table('WIKI/PRICES', ticker=app.vars['current_symbol'], qopts = {'columns':['ticker', 'date', 'adj_close']}, date = {'gte': '2017-11-01', 'lte': '2017-12-01'}, paginate = True)
req_data.adj_close = round(req_data.adj_close, 2)
req_data = req_data.set_index('date')
cleaned_data = req_data.pivot(columns = 'ticker')
# Plot the data
p = figure(x_axis_type='datetime', x_axis_label='Date', y_minor_ticks=2, plot_width = 800, plot_height = 600)
p.line(x = cleaned_data.index, y = cleaned_data.adj_close, line_width = 2)
script, div = components(p)
return render_template('plot.html', script=script, div=div)
if __name__ == "__main__":
app.run(debug=True)
Here are the accompanying HTML files.
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stock Plotter</title>
<link href="https://cdn.bokeh.org/bokeh/release/bokeh-1.2.0.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.2.0.min.js"></script>
<!-- <link rel="icon" href="favicon.ico"> -->
<title>Stock Plotter</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class=metanav>
<h1>Stock Plotter</h1>
<div>
<form id="tickerform" action="/plot" method="POST">
Ticker Symbol: <input type="text" name="current_symbol" placeholder="ticker symbol"></input> <!--Create a dropdown list with the following options=-->
<div>
<input type="submit" value="Submit"></input> <!--Create the submit button-->
</div>
</form>
</div>
{{ script|safe }} <!--Marks the js scrips as safe for the web-->
{{ div|safe }}
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
plot.html
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bokeh.org/bokeh/release/bokeh-1.2.0.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.bokeh**strong text**.org/bokeh/release/bokeh-1.2.0.min.js"></script>
<title>Stock Plotter</title>
</head>
<body>
<div class=page>
<h1>Stock Plotter</h1>
{{ script|safe }}
{{ div|safe }}
</div>
</body>
</html>
I expect the plot to be visible, but it's not.
No error messages are shown in the console.
Check this post:
Embedding multiple bokeh HTML plots into flask
It has a great example as to how to display bokeh figures in flask apps.
For anyone looking for an answer, the problem with this code is that the plot definition (p.line...) has some problem with my defining the x and y values explicitly. Once I used the source argument, the plot appears as desired.