Skip to main content
 首页 » 编程设计

python之如何在 Flask 中使用 AJAX 遍历列表

2024年12月31日35kenshinobiy

问题

我正在尝试在 Flask 中使用 AJAX 显示图像文件。更具体地说,我想在单击按钮后显示图像,并在再次单击按钮后显示下一张图像(如幻灯片)。图像的文件名存储在我的数据库中。我查询数据库以获取当前用户的文件名列表,并将每个文件名与路径的其余部分(图像存储在磁盘上的路径)组合起来以显示图像。

到目前为止,我设法获得了当前用户的第一张图片。但是,我想不出一种方法来跟踪下一张要显示的图像。

我尝试使用全局变量作为计数器 (file_counter),它应该用作索引。我想在每次发出 ajax 请求时将 file_counter 增加 1 以获取下一个文件,但计数器不会在后续调用时增加,也不会引发错误。

问题

我需要如何初始化全局变量 (file_counter) 以便它在多个调用中存储它的值?此外,使用全局变量是否是执行此操作的正确方法?

HTML

<div id="ajax-field"></div> 
<button class="btn btn-block"  id="next-button"><p>Next Image!</p></button> 

Ajax :

$('#next-button').click(function(){ 
         $("#ajax-field").text(""); 
         $.ajax({ 
                        url: "/get_data", 
                        type: "POST", 
                        success: function(resp){ 
                            $('#ajax-field').append(resp.data); 
                        } 
                    }); 
                        }); 

路由:

global filenames 
global file_count 
@app.route("/get_data", methods=['POST']) 
def get_data(): 
    try: # Is intended to fail on the first run in order for the global variables to be initialized. However it keeps failing on subsequent runs 
        display_img = filenames[file_count] 
        file_count +=1 
    except: 
 
        filenames = [] 
        # current_user.uploads returns all file-objects of the current user 
        user_uploads = current_user.uploads 
        for file in user_uploads: 
            # file.filename returns the respective filename of the image 
            filenames.append(file.filename) 
        #filenames is now a list of filenames i.e. ['a.jpg','b.jpg','c.jpg'...] 
        display_img = filenames[0] 
        file_count = 1 
 
    path = "image_uploads/4_files/"+display_img 
 
    return jsonify({'data': render_template('ajax_template.html', mylist = path)}) 

ajax_template.html:

<ul> 
{% block content %} 
    <li> 
        <img id="selected-image-ajax" src="{{url_for('static',filename=mylist)}}"  class="img-thumbnail" style="display:block; margin:auto;"></img> 
    </li> 
{% endblock content %} 
</ul> 

请您参考如下方法:

正如@roganjosh 所指出的,session 是跨多个请求存储信息的最佳方式。此解决方案展示了使用 flask.session 存储计数器的照片显示实现:

import flask, random, string 
app = flask.Flask(__name__) 
app.secret_key = ''.join(random.choice(string.printable) for _ in range(20)) 
#to use flask.session, a secret key must be passed to the app instance 
 
@app.route('/display_page', methods=['GET']) 
def display_page(): 
  '''function to return the HTML page to display the images''' 
  flask.session['count'] = 0 
  _files = [i.filename for i in current_user.uploads] 
  return flask.render_template('photo_display.html', photo = _files[0]) 
 
@app.route('/get_photo', methods=['GET']) 
def get_photo(): 
   _direction = flask.request.args.get('direction') 
   flask.session['count'] = flask.session['count'] + (1 if _direction == 'f' else - 1) 
   _files = [i.filename for i in current_user.uploads] 
   return flask.jsonify({'photo':_files[flask.session['count']], 'forward':str(flask.session['count']+1 < len(_files)), 'back':str(bool(flask.session['count']))}) 

当用户访问/display_page 路由时,将调用display_page 函数并将计数设置为0。 get_photo 绑定(bind)到 /get_photo 路由,将在发送 ajax 请求时调用。

photo_display.html:

<html>  
  <head> 
   <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> 
   </head> 
   <body> 
      <div class='image_display'> 
        <img src="{{photo}}" id='photo_display' height="100" width="100"> 
        <table> 
         <tr> 
           <td class='back'></td> 
           <td class='forward'><button id='go_forward' class='navigate'>Forward</button></td> 
         </tr> 
        </table> 
      </div> 
   </body> 
   <script> 
    $(document).ready(function(){ 
      $('.image_display').on('click', '.navigate', function(){ 
        var direction = 'b'; 
        if ($(this).prop('id') === 'go_forward'){ 
          direction = 'f'; 
        } 
 
        $.ajax({ 
         url: "/get_photo", 
         type: "get", 
         data: {direction: direction}, 
         success: function(response) { 
           $('#photo_display').attr('src', response.photo); 
           if (response.back === "True"){ 
             $('.back').html("<button id='go_back' class='navigate'>Back</button>") 
           } 
           else{ 
             $('#go_back').remove(); 
           } 
           if (response.forward === "True"){ 
             $('.forward').html("<button id='go_forward' class='navigate'>Forward</button>") 
           } 
           else{ 
             $('#go_forward').remove(); 
           } 
 
         }, 
 
       }); 
      }); 
    }); 
   </script> 
</html> 

display_page.html 中的javascript 与后端通信,并相应地更新img 标签src。该脚本根据当前计数值添加或删除导航按钮。


演示:

为了测试上面的解决方案,我创建了一个图像文件夹来存储要显示的随机照片: