How to redirect when a server-dispatched event is completed in Flask on the server side?

Question

How can I redirect to another page when the server-sent event is completed in Flask and on the server side?

Description of the problem

EventSource was implemented on the client side (JavaScript), and the response was returned on the server side (Flask, Python). EventSource will be closed if the last item was sent from the server. I do not see a clear solution for redirecting to another site using server-side code. Perhaps the answer is simple, but I do not understand.

Similar problem

A similar question. How to stop server-related events, and one of the possible answers in the comment How do events go to the server? . I'm not sure if this is the same for php and python, so I started a new question for this. I don’t get it either.

EDIT How to close a Server-Send Events connection in Flask? strongly related to this issue. The question basically is how you can stop SSE from Flask.

Client-side working solution

So, I came up with a solution that worked (progress bar), but only on the client side. How do I change the code to get a working example of reconnecting through Flask functions?

Matching code snippets

HTML / Jinja

{% block additional_stylesheets %} <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> <link rel="stylesheet" href="{{ url_for('static', filename='data_import.css') }}" /> {% endblock %} {% block additional_javascripts %} <script src="{{ url_for('static', filename='js/data_import.js') }}"></script> {% endblock %} {% block content %} <div class="progress"> <div class="progress-bar progress-bar-striped active" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"> </div> </div> {% endblock %} 

Javascript

 $(document).ready(function() { var source = new EventSource("/progress"); source.addEventListener('import-progress', function(event) { $('.progress-bar') .css('width', event.data + '%') .attr('aria-valuenow', event.data); }, false ); source.addEventListener('last-item', function() { source.close(); redirect(); }, false ); } ); # This works! But how to do the same thing without calling redirect() # on client site? function redirect() { window.document.location.href = window.location.protocol + "//" + window.location.host + "/products.html"; } 

Flask

 from foo import app from flask import render_template, Response @app.route('/data_import.html') def data_import(): return render_template( 'data_import.html') @app.route('/progress') def progress(): return Response(import_progress(), mimetype='text/event-stream') def import_progress(): """ Just a small example """ for number in range(1, 101): sse_id = str(number) sse_progress = str(number) sse_event = 'import-progress' if number == 100: sse_event = 'last-item' yield "id:{_id}\nevent:{event}\ndata:{progress}\n\n".format( _id=sse_id, event=sse_event, progress=sse_progress) 

I worked hard to get redirected work. But I don’t know exactly how to do this. Each attempt has so far failed.

+4
source share
1 answer

What you want to do is send the redirect URL as the last event - you still have to redirect using JavaScript, but you no longer have to hard-code the path:

 def import_progress(): """ Just a small example """ for number in range(1, 101): sse_id = str(number) sse_data = str(number) sse_event = 'import-progress' if number == 100: sse_event = 'last-item' sse_data = url_for('product_list') yield "id:{_id}\nevent:{event}\ndata:{data}\n\n".format( _id=sse_id, event=sse_event, data=sse_data) 

Then your last element handler becomes:

 source.addEventListener('last-item', function(event) { source.close(); redirect(event.data); }, false ); 

And redirect becomes simple:

 function redirect(url) { document.location = url; } 
+4
source

Source: https://habr.com/ru/post/921054/


All Articles