Search code examples
pythonhtmlflaskbutton

Flask: How to transfer an element from one app.route to another


I am currently working on a project in which I have an archive, in which you should be able to remove videos from a button in a webpage. As I implement the webpage via python I have troubles naming the name of the button as the index, (idx) declared in the for loop. I need to have the name of the button clicked (index) (or directly the file name) in the /delete app route but cannot figure out how to transfer it properly. The Button itself works.

@app.route('/archive' , methods=['GET', 'POST'])
def archive():  
  
    path = "/home/pi/Videos/"
    print("Files and directories in '", path, "' :")  
    dir_list = os.listdir(path) 
    dir_list.sort()               # The List
    

    output = '''<!DOCTYPE html><html lang="en">... #just some styling
        <div class = Box>
        <div class = flex-box>'''
    
    
    for idx, file in enumerate(dir_list):              #For loop through each element
            
            output += "<div style = 'background: black;'>"+ file +  "</div>" + ''' <form method='post' action='myip/delete'>
    <input class='btn' type='submit' name=idx value='Delete'> </form> ''' 
    output += "</div></div>"
    return output

    
@app.route('/delete', methods=['GET', 'POST'])
def delete_file():
      output = request.form['idx'] 
      os.remove(THEFILEIWANTTODELETE)                    #HERE I NEED TO HAVE THE INDEX OR FILE NAME/ROUTE
      return redirect(url_for('archive'))
        

I already tried getting the index, but only got the value of the button.


Solution

  • Based on your example, here's a possible solution to start with.

    To display the page, as @roganjosh mentioned, you can use jinja with either render_template or render_template_string. Jinja is a built-in template engine that you can pass a template and a dictionary with data to. This data can then be used in various ways within the template based on its key

    To specify the file to delete, I think the easiest way is to send the filename. In this case a path within a variable rule is used.

    from flask import (
        Flask, 
        redirect, 
        render_template_string, 
        url_for
    )
    import os 
    
    app = Flask(__name__)
    
    @app.route('/archive')
    def archive():  
        path = '/home/pi/Videos/'
    
        dir_list = os.listdir(path) 
        dir_list.sort()
        
        return render_template_string(
            '''
            <!DOCTYPE html>
            <html lang="en">
            <!-- ... -->
            <body>
                <div class="box">
                    <div class="flex-box">
                        {% for file in dir_list -%}
                        <div>
                            {{ file }}
                            <form method="post" action="{{ url_for('.delete', filename=file) }}">
                                <input type="submit" value="Delete" />
                            </form>
                        </div>
                        {% endfor -%}
                    </div>
                </div>
            </body>
            </html>
            ''', 
            **locals()
        )
    
    @app.post('/delete/<path:filename>')
    def delete(filename):
        path = '/home/pi/Videos/'
        try: 
            os.remove(os.path.join(path, filename))
        except: pass
        return redirect(url_for('archive'))