Read a python rewritten image in Flask - python

I have code using Flask as given below:
app = Flask(__name__,static_url_path='/static')
#app.route('/')
def my_form():
return render_template('my-form.html')
#app.route('/result', methods=['POST'])
def result():
text = request.form['Name']
sentiment = generateimage(text)
return render_template("result.html")
my-form.html
<div class="col-lg-1"></div>
<div class="col-lg-10">
<form action="http://localhost:5505/result" method="POST">
<div class="form-group">
<label for="comment">Text</label>
<textarea class="form-control" rows="10" cols="4" id="comment" name="Name"></textarea>
</div>
<input type="submit" class="btn btn-info" value="Analyze">
</form>
</div>
</div>
result.html
<img src ="/static/fig1.png"/>
What flask.py does is grab the text from my-form, process it and generate an image in a static folder, but when the result.html page loads up it displays the previously generated image and not the most recent one.
How do I solve this issue?
def generateimage(text)
######some code######
plt.savefig('/home/aurora/Desktop/sentiment/static/fig1.png', dpi=dpi)

I'll assume that this is a caching issue, otherwise your first call to the system would not produce an image at all. A quick and dirty hack is to just force your image not to be cached by adding a random query string after the image URL within the result.html:
<img src ="/static/fig1.png?{{no_cache}}"/>
And then just call it from your Flask app as:
return render_template("result.html", no_cache=time.time()) # import time, of course
This, kind of, defeats the purpose of static content - if you're always going to render the image based on user input there is little point in storing it at all - just create a different Flask endpoint that will render the image directly to the user without ever storing it and call that instead of the image's static URL.

Related

Python Flask: User Downloading Scraped Images

I have a little script that is an image scraper. Essentially, you provide the script with a link and it downloads all the images on the webpage to a folder on your desktop. I would like the same functionality but on the browser. I ant users to enter a link and the script starts downloading the images from the link to their computer. My Code Is Below:
#app.route('/')
def main():
return render_template('index.html')
#app.route('/Downlading', methods=['POST'])
def Downlading():
url= request.form['url']
start = request.form['start']
end = request.form['end']
dphy = image_downloader(url) #this is the script that saves the images
return str(dphy)
I am able to get the user url and pass it to image_downloader, which downloads the images. The problem is that the images get downloaded from the command prompt. I want the script to run inside the browser, just like it would run in my IDE. Sorry if this is confusing.
My HTML code:
<form action="/Downlading" method="POST" >
URL: <input type="text" name="url"><br/>
Start: <input type="text" name="start"><br/>
End: <input type="text" name="end"><br/>
<input type="submit" name="form" value="Submit" />
</form>
You need to create an HTML template for the variable to be reflected on. For example:
HTML - upload.html:
<html>
<title>Example on StackOverflow</title>
<p> The str representation of the variable dphy is {{ dphy }} </p>
</html>
Python (add this to existing flask script):
#app.route('/Downlading', methods=['POST'])
def Downlading():
url= request.form['url']
start = request.form['start']
end = request.form['end']
dphy = image_downloader(url) #this is the script that saves the images
return render_template('upload.html', dphy=str(dphy))
This should work, but I can't test it right now so I'm not positive. This is the basic idea for passing variables through Flask - create a template that uses the variable, then pass it in explicitly when rendering that created template.

Serving image files from the database to the template

I am stuck trying to figure out how to serve images files from a GET Request on a button in my html document; when the button is clicked it loads the image to the page. The files are stored in a directory for example: /model/modelrun/region/myimage.png I understand that the path to the image should be stored in the database:
page.html:
<div class="btn-group btn-group-justified" role="group" aria-label="...">
<form action="#" method="GET" class="navbar-form navbar-left" role="form">
<div class="btn-group" role="group">
<button type="button" class="btn btn-default">GFS</button>
</div>
</form>
</div>
<iframe src="{% url 'new_model_image' }" ></iframe>
models.py:
from django.db import models
class NModels(models.Model):
model_name=models.CharField(max_length=30)
class Modelrun(models.Models):
currmodel = models.ForeignKey(NModels)
run_name = models.CharField(maxlength=20)
class MRegion(models.Models):
model_run = models.ForeignKey(Modelrun)
region = models.CharField(max_length=20)
class ModelImages(models.Model):
finalmodel = Models.ForeignKey(MRegion)
timestep = models.IntegerField(max_value=3)
picture = models.ImageField(upload_to=pathtomyimagefiles)
Reasoning: Every model will have multiple model runs of different regions where there will be multiple images for a given time step (maybe I need to separate these last two).
views.py:
def model_page(request):
if request.method =='GET':
[get image path and load into iframe]
return render(request, 'models.html')
Here's where I get lost with trying to use the GET request to get the path to the image to the database to load into the iframe.

How to call a different render after a form submission

I'm diving into Flask for the first time and I'm having some trouble getting something work.
I currently have a template for when my tab values is empty, it contains a form that when submitted should call a specific function using the parameters of the form and return another template. Each call of the form should in, fact call the index.html template with different values.
Relevant parts of code are as follows:
main.py
#app.route('/', methods=['POST','GET'])
def main():
global maxDepth, numberOfRelated
if not values:
return render_template('initial.html')
if request.method=='POST':
url = request.form['url']
maxDepth = request.form['depth']
numberOfRelated = request.form['numberOfRelated']
values = crawling(url,maxDepth,numberOfRelated)
return render_template('index.html',var=values)
The form part of initial.html and index.html are actually the same
<form class="form-inline" action="/" method="POST">
<div class="form-group">
<input name='url' type="text" class="form-control"/>
</div>
<div class="form-group minorForm">
<input name='numberOfRelated' type="text" class="form-control" />
</div>
<div class="form-group minorForm">
<input name='depth' type="text" class="form-control" />
</div>
<div class="form-group navbar-right">
<button class="btn btn-success minorForm generate" type="submit"> Generate</button>
</div>
</form>
In your main method, unless values is global, it won't be defined for if not values.
As to your question, add another render_template call just after the conditional for if the form was submitted:
if request.method=='POST':
url = request.form['url']
maxDepth = request.form['depth']
numberOfRelated = request.form['numberOfRelated']
values = crawling(url,maxDepth,numberOfRelated)
return render_template('index.html',var=values) # 1
return render_template('index.html',var=values) # 2
If the form is submitted, the conditional will be true and the template will be rendered at comment #1. If the user is navigating to the page normally, the conditional will be false and the line with comment #2 will be called.
I'm a bit confused about the question, but you should always redirect after a POST (unless there was an error in the form and no action was taken). That way the same action won't be repeated if the user reloads the page.

Bottle: Global Variable 'request' is not defined

I am creating a web based application with python where the user enters a search query and data is returned. I used bottle to provide the web framework for this. Openshift is then used to post online. It is a simple post form and the search criteria is then used in the next section using this:
#route('/')
def search():
return '''
<h1 align="center">Twitter Sentiment Analysis</h1>
<p align="center">Enter what you would like to search in the search box below</p>
<form action="/result" method="post" align="center">
Search: <input name="search" type="text" />
<input value="Search" type="submit" />
</form>
'''
#route('/result', method='POST')
def result():
search = request.forms.get('search')
return 'it worked'
When using bottle and tested it, it worked fine, but when I try to deploy it to OpenShift, I get a name error, "global variable 'request' is not defined" when in testing it worked perfectly with just bottle before deploying to openshift, does anyone know why this may be?
It seems like you haven't imported the request or route to namespace:
from bottle import get, post, request # or route
#get('/login') # or #route('/login')
def login():
return '''
<form action="/login" method="post">
Username: <input name="username" type="text" />
...
'''
#post('/login') # or #route('/login', method='POST')
def do_login():
user = request.forms.get('username')
pass = request.forms.get('password')
...

Pyramid app: How can I pass values into my request.route_url?

I have this in my views.py file as the view config for my home page:
#view_config(route_name='home_page', renderer='templates/edit.pt')
def home_page(request):
if 'form.submitted' in request.params:
name= request.params['name']
body = request.params['body']
page=Page(name,body)
DBSession.add(page)
return HTTPFound(location=request.route_url('view_page',pagename=name))
return {}
Also, here is the form in the edit.pt template:
<form action="/view_page" method="post">
<div>
<input type="text" name="name"/>
</div>
<div>
<input type="text" name="body"/>
</div>
<label for="stl">Stl</label>
<input name="stl" type="file" value="" />
<input type="submit" name='form.submitted' value="Save"/>
</form>
Also in my init.py file I have
config.add_route('home_page', '/')
config.add_route('view_page', '/{pagename}')
right now when I submit the form it just tries to go to localhost:6543/view_page. This returns a 404 as there is no view_page resource or route leading to it. Instead I want it to go to localhost:6543/(the name of the page I just created aka the first input box in the form). How can I do this?
Edit: I am worried that something else may be telling it to route to view_page because I even tried changing it to
return HTTPFound(location=request.route_url('front_page',pagename=name))
And it still goes to /view_page. There is no route named front_page, so I would at least suspect it to throw an error.
Also, I would really appreciate it if you could tell me where you found the info. I have been looking at http://docs.pylonsproject.org/projects/pyramid/en/1.4-branch/api/request.html?highlight=request.route_url#pyramid.request.Request.route_url but can't seem to find use from it.
Edit: should I be using an asset specification instead of a path name? so
return HTTPFound(Location=request.route_url('tutorial:templates/view.pt','/{pagename}'))
Also, I am working through this article which seems very helpful with the syntax: http://docs.pylonsproject.org/projects/pyramid/en/latest/narr/urldispatch.html#urldispatch-chapter
I think your form should submit to "/", ie.
<!-- where your home_page route is waiting for the POST -->
<form action="/" method="post">
With the prior answers this now looks correct:
return HTTPFound(location=request.route_url('view_page', pagename=name))
My first guess is that it's location not Location as the argument to HTTPFound.
from the link you give
it's should be
return HTTPFound(location=request.route_url('view_page',pagename=name))
when you had add this route
config.add_route('view_page', '/{pagename}')
and set the variable name before
name= request.params['name']

Categories

Resources