Return Image from python CGI using javascript

2019-06-06 10:41发布

I am using Python CGI to create a webpage that shows a title, dropdown menu and image. I would like to be able to select an option from the dropdown menu (would love to get rid of "submit" as well and just run when an option is chosen), trigger my python code (runthis.py) and update the image on the webpage. I want to do this WITHOUT opening new tabs and hopefully without refreshing the page. Currently I run this .py file to get my html:

#!C:\Python27\python

print "Content-type: text/html"
print

print "<html>"
print "<head>"
print "<title>Tab Title</title>"

print "</head>"
print '''<body bgcolor="#ccffcc">'''

print '''<h1 align="center">Page Heading</h1>'''

print '''<form action="/cgi-bin/dropdown.py" method="post" target="_blank">'''
print '''<select name="dropdown">'''
print '''<option value="Option1" selected>Option1</option>'''
print '''<option value="Option2" selected>Option2</option>'''
print "</select>"
print '''<input type="submit" value="Submit"/>'''
print "</form>"

print "<img src = /test.png>"

print "</body>"
print "</html>"

When I click "submit", a new tab will open showing the same page layout, just a different image (same one for example's sake). This is done through my dropdown.py file in cgi-bin:

#!C:\Python27\python

import cgi,cgitb,os
cgitb.enable()

os.environ['HOME']='C:\python_cgi'

import matplotlib
matplotlib.use('Agg')

form = cgi.FieldStorage()

if form.getvalue('dropdown'):
    subject = form.getvalue('dropdown')
else:
    subject = "Not Entered"

from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
import StringIO

import msvcrt,sys, urllib, base64

fig = Figure(figsize=[4,4])
ax = fig.add_axes([.1,.1,.8,.8])
ax.scatter([1,2],[3,4])
canvas = FigureCanvasAgg(fig)

imgdata = StringIO.StringIO()
fig.savefig(imgdata, format='png')
imgdata.seek(0)

uri = 'data:image/png;base64,' + urllib.quote(base64.b64encode(imgdata.buf))

print "Content-Type: text/html"
print

print """\

<html>
<head>
<title>Tab Title</title>

</head>
<body>
  <body bgcolor="#ccffcc">
  <h1 align="center">Page Heading</h1>

  <form action="/cgi-bin/dropdown.py" method="post" target="_blank">
    <select name="dropdown">
      <option value="Option1" selected>Option1</option>
      <option value="Option2" selected>Option2</option>
    </select>
    <input type="submit" value="Submit"/>
  </form>

  <img src = %s/>

</body>
</html> """ % uri

To recap -- I just want to change the picture/image on the current page rather than opening up a whole new page. My gut tells me to use javascript (which I know nothing about). Does anyone have a suggestion on a code block that I need to enter to do such a thing?

Thanks!

EDIT

Per the comments below, I am trying to implement this html file:

<html>
<head>
<title>Tab Title</title>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js" ></script>

</head>
<body>

<script>
  function changeImage(imgName)
{
     jQuery.get('/cgi-bin/dropdown.py', function(data) {
     image = document.getElementById('imgDisp');
     image.src = data;
    })

  }
</script>


  <body bgcolor="#ccffcc">
  <h1 align="center">Page Heading</h1>

  <select name="dropdown" onchange="changeImage(this.value)"> 
  <option value="Option1">Option1</option>
  <option value="Option2">Option2</option>
  </select>

  <img id="imgDisp" src="/test.png" />

</body>
</html>

This loads my page correctly but nothing happens when I make a selection from the dropdownlist. I was hoping the image would change. My "dropdown.py" code now looks like:

#!C:\Python27\python

import cgi,cgitb,os
cgitb.enable()

os.environ['HOME']='C:\python_cgi'

import matplotlib
matplotlib.use('Agg')

from matplotlib.figure import Figure
from matplotlib.backends.backend_agg import FigureCanvasAgg
import StringIO

import msvcrt,sys, urllib, base64

fig = Figure(figsize=[4,4])
ax = fig.add_axes([.1,.1,.8,.8])
ax.scatter([1,2],[3,4])
canvas = FigureCanvasAgg(fig)

imgdata = StringIO.StringIO()
fig.savefig(imgdata, format='png')
imgdata.seek(0)

uri = 'data:image/png;base64,' + urllib.quote(base64.b64encode(imgdata.buf))
return uri

I haven't gotten to the url parameter approach yet -- not sure how that is done. Any more advice would be greatly appreciated!

1条回答
姐就是有狂的资本
2楼-- · 2019-06-06 11:25

In response to your edited question, the solution can actually be simpler:

function changeImage(imgName) {
     jQuery.get('/cgi-bin/dropdown.py', function(data) {
     image = document.getElementById('imgDisp');
     image.src = data;
    })
}

Here you are making an asynchronous request to your Python script, and waiting for some data to be returned. However, you could consider your Python script a standalone service that maps, so to speak, a unique set of parameters to a (dynamically generated) image. This requires your Python script to output the image to the browser instead of returning the image data through CGI:

imgdata = StringIO.StringIO()
fig.savefig(imgdata, format='png')
imgdata.seek(0)

#Something along these lines
print "Content-Type: img/png\n"
imgdata.seek(0)
print imgdata.read()

Once you are confident that an HTTP request to your Python script serves up a valid PNG, your front-end code only has to update the src attribute of the image you are displaying:

function changeImage(imgName) {
    var url = "http://localhost:8000/cgi-bin/dropdown.py?image=" + imgName;
    var img = jQuery('#imgDisp');
        img.src = url;
}

When your img element is given a new src value, the browser will automatically make a request to that URL and try to retrieve an image, which will load onto your page, replacing the previous image. You would have to modify your Python script, however, to expect a request parameter named image, which holds a string. CGI has a simple method for accessing these parameter values passed inside the URL:

#Example CGI script
if __name__ == "__main__":
    params = cgi.FieldStorage()
    if "image" in params:
        img = params['image']
        #Generate the image and output it with the correct headers
    else:
        #Exception handling
        print "Content-Type: text/html\n"
        print """<html><body>No image name was specified!</body></html>"""

This page is a great resource that you can check out: http://lost-theory.org/python/dynamicimg.html

查看更多
登录 后发表回答