Возврат изображения из Python CGI с использованием javascript

Я использую Python CGI для создания веб-страницы с заголовком, выпадающим меню и изображением. Я хотел бы иметь возможность выбрать вариант из раскрывающегося меню (хотелось бы также избавиться от «отправить» и просто запустить, когда выбран вариант), запустить мой код Python (runthis.py) и обновить изображение на веб-страница. Я хочу сделать это БЕЗ открытия новых вкладок и, надеюсь, без обновления страницы. В настоящее время я запускаю этот файл .py, чтобы получить свой 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>"

Когда я нажимаю «отправить», открывается новая вкладка, показывающая тот же макет страницы, только другое изображение (то же самое, например). Делается это через мой файл dropdown.py в 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

Резюмируя: я просто хочу изменить изображение/изображение на текущей странице, а не открывать совершенно новую страницу. Моя интуиция подсказывает мне использовать javascript (о котором я ничего не знаю). Есть ли у кого-нибудь предложение по блоку кода, который мне нужно ввести, чтобы сделать такую ​​​​вещь?

Спасибо!

ИЗМЕНИТЬ

В комментариях ниже я пытаюсь реализовать этот html-файл:

<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>

Это правильно загружает мою страницу, но ничего не происходит, когда я делаю выбор из раскрывающегося списка. Я надеялся, что образ изменится. Мой код "dropdown.py" теперь выглядит так:

#!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

Я еще не дошел до подхода к параметру URL - не уверен, как это делается. Любые дополнительные советы будут очень признательны!


person mcfly    schedule 10.02.2014    source источник
comment
Я думаю, что было бы лучше создать простую HTML-форму, которая позволяет пользователю указывать параметры изображения (через форму), а затем использовать JavaScript для анализа ввода, упаковки значений формы в объект и отправки его в отдельный Скрипт Python как переменная POST. Единственной обязанностью скрипта Python будет чтение объекта/параметров и вывод соответствующих заголовков и данных изображения. Когда пользователь нажимает «отправить», ваш Javascript может отправить запрос AJAX в Python, получить изображение и использовать его для создания нового элемента img в DOM.   -  person Michael Zalla    schedule 11.02.2014
comment
Лучше отделить презентацию от логики. Ваш «бэкэнд» код должен принимать только параметры и отображать ответ (изображение). Возможно, самый простой способ сделать это — разработать схему параметров URL (например, /cgi-bin/myscript.py?option=1) для вашего сценария и получить доступ к значениям параметров в сценарии CGI с помощью класса FieldStorage (см. python.org/2/library/cgi.html#id1" rel="nofollow noreferrer">docs.python.org/2/library/cgi.html#id1). Ценность этого дизайна заключается в простоте интерфейса.   -  person Michael Zalla    schedule 11.02.2014
comment
В этом сценарии целью вашего кода JavaScript будет чтение значений формы, создание пользовательского URL-адреса для вашего сценария Python (см. stackoverflow.com /questions/6566456) и задайте для атрибута src элемента изображения этот URL.   -  person Michael Zalla    schedule 11.02.2014
comment
Если я использую схему javascript в последнем комментарии, как мне запустить код Python в основном файле html? Если я понимаю, я бы выбрал раскрывающийся список, затем javascript будет запущен для создания URL-адреса, но как мне тогда запустить мой скрипт python? Кроме того, где я могу установить атрибут src в моем скрипте Python? Не знаю, как вернуть данные. Спасибо!   -  person mcfly    schedule 11.02.2014


Ответы (1)


В ответ на ваш отредактированный вопрос решение может быть проще:

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

Здесь вы делаете асинхронный запрос к вашему скрипту Python и ожидаете возврата некоторых данных. Однако вы можете рассматривать свой скрипт Python как отдельную службу, которая, так сказать, сопоставляет уникальный набор параметров с (динамически генерируемым) изображением. Для этого ваш скрипт Python должен выводить изображение в браузер, а не возвращать данные изображения через 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()

Как только вы будете уверены, что HTTP-запрос к вашему скрипту Python обслуживает действительный PNG, ваш интерфейсный код должен обновить только атрибут src изображения, которое вы отображаете:

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

Когда вашему элементу img будет присвоено новое значение src, браузер автоматически сделает запрос к этому URL-адресу и попытается получить изображение, которое загрузится на вашу страницу, заменив предыдущее изображение. Однако вам придется изменить свой скрипт Python, чтобы ожидать параметр запроса с именем image, который содержит строку. CGI имеет простой метод для доступа к этим значениям параметров, переданным внутри 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>"""

Вы можете проверить эту страницу: http://lost-theory.org/python/dynamicimg.html

person Michael Zalla    schedule 11.02.2014