using ajax in flask to load live logs - javascript

I am looking for some help, regarding my web server. I have a flask web server, designed to search in log files, and it does the job, but I need something else. To access the live data, to see the logs live.
It's an internal application, so the security is not a concern. The main thing it should do, is to open a file and basically simulate a "tail" command.Read the last lines, then just append the new ones, and basically that's all.
I was thinking to go with an AJAX call, but i'm not really good (at all) with JavaScript.
I was wondering about this solution :
var byteRead=0;
setInterval(function(){
$.ajax({
type: "GET",
url: "GenNumber.txt",
dataType: "text",
success: function (data) {
byteRead+= data.length;
readdata(data);
},
headers: {
"Range" : "bytes="+byteRead+"-"
}
});
},1000);
But im not quiet sure about it... neither how to adapt it (js side).
Does anyone have experience with this kind of issues or ideea how to start ?

So, in short terms in case of anyone else needs something like this, the solutin is :
#login_required
def live():
return render_template('live.html',user=current_user)
#views.route('/live_logs', methods=['GET', 'POST'])
def live_logs():
if request.method == 'GET':
def generate():
var_live = ''
var = sp.Popen(['tail','-f',var_live],stdout=sp.PIPE,stderr=sp.PIPE)
while True:
var_live_log = var.stdout.readline()
var_live_log = var_live_log.decode('utf-8')
yield "data:" + str(var_live_log) + "\n\n"
time.sleep(0.1)
return Response(generate(), mimetype= 'text/event-stream')
And the HTML file should look like this :
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<br>
<hr>
<section class="section">
<div class="livelog">
<div class="columns is-centered is-mobile">
<div class="column is-dark notification is-four-fifths">
<div class="is-size-7 has-text-warning" id="display">
<ul id="display_list" class="logs"></ul>
</div>
</div>
</div>
</div>
</section>
</body>
</html>
{% endblock %}
Obviously this may differ, based on base.html
But this code will create a tail session which and stream it to the browser, also can be modified to read a file or smth..

Related

Django: Call Python Function on Button Click and Display String

I found a couple of resources online, but none that worked for me. Here is what I currently have:
In views.py:
def button(request):
return render(request, 'home.html')
def display_text(request):
return HttpResponse('TESTING', status=200)
In urls.py:
urlpatterns = [
url(r'^$', views.button),
url(r'^display_text', views.display_text, name='script'),
]
In home.html:
<div class="row">
<input type="text" class="form-control js-text" id="input-box" placeholder="Type something to begin..."/>
<div class="col-md-12" style="text-align:center;">
<button onclick="location.href='{% url 'script' %}'"></button> <hr>
</div>
</div>
What happens right now is that it displays the string on a new web page. What I want to do is populate my text-box with that string returned by my Python function, and display it on the current page. How can I do so? Thanks!
The easiest way to do this is to make use of the render function provided by Django. This function combines a context and a template and renders a HttpResponse. You can change the display_text function to the following:
def display_text(request):
return render(request, 'home.html', {'string': 'TESTING'})
#Im assuming home.html is the the page you want to render
Now you can make use of Django templates to show the data sent through the context like so:
<div>
<p>{{string}}</p>
</div>

Button with full ajax flask implementation doing absolutely nothing

I'm trying to use a custom search bar on my flask app. I didn't manage to associate it to a form (or flask-wtform) and retain its animations. Therefore I choose to implement ajax, which I'm also very interested to see working with flask.
My problem is that no matter what I do, the button does absolutely nothing!
HTML
{% block header %}
<div class="py-5 bg-image-full bgpic1">
<img class="logotipo img-fluid d-block mx-auto" src="/static/img/cerveweb_inverted.png">
<div class="searchBox">
<input id="txtBusqueda" class="searchInput" type="text" placeholder="Buscar">
<button id="btnBusqueda" class="searchButton">
<i class="fas fa-search"></i>
</button>
</div>
</div>
{% endblock %}
JavaScript
<script type="text/JavaScript">
function buscar(){
alert("2");
var texto = $("#txtBusqueda").val();
$.ajax({
url: "{{url_for('buscar')}}",
type: 'POST',
data: {'data':texto},
contentType: 'application/json;charset=UTF-8'
});
};
$("#btnBusqueda").click(function(){
console.log("1");
buscar();
});
</script>
Flask
#main.route('/buscar', methods=['GET', 'POST'])
def buscar():
# Viene de un AJAX
if request.method == "POST":
texto = request.json['data']
flash("Has buscado: {}".format(texto), "info")
return render_template('index.html')
EDIT:
Enclosing the scripts of the Jinja template, extending the functionality of a block of a base template made it work. However I'm confused about it, shouldn't scripts survive the rendering?
Also, for some reason now it is pointing out that its a bad request:
This is the current code of the script and flask:
It appears that flask has no good compatibility with Ajax, you have to switch to json to handle the Ajax request. Wich in medium to bigger sized app models with sqlalchemy is a pain. My approach was to map sqlalchemy objects directly to json counterparts using marshmallow ORM. Turning the app into a mix of classic flask-wtf and api rest.
I must clarify that I did this refactor with time as major factor, prioritizing speed over performance.
There are some pretty elegant solutions out there that don't need such mix, but I could not stop to analize them in depth. They just could not compete with the very short amount of extra lines of code I needed. (around 3 per model class, and 2 for to call it)
However, I did not manage under any circumstances to make flask respond correctly the variables to Ajax. This problem was temporarily fixed using flask session, wich works line a charm.

Python Flask: Return HTML Content

i am trying to put together a makeshift tool for my own personal use, im not experienced with backend development at all. so my methods may be unconventional. although there may be a much better method to go about this
consider the following snippet from my html file:
<tr><td>
<button id="socks.shirt.pants"> dummy text here </button>
</td></tr>
my goal, as simply as i can put it, is to click BUTTON and return the string text within the ID attribute in python using Flask. Below is the code i am working with.
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
#display html file
return send_from_directory('','myfile.html')
#this is the part that needs help
textdata = request.htmlcontent.td.id
i have tried several different ways to extract the html content. including but not limited to:
request.html.tr.id,
request.get_data(),
request.data(),
request.form,
i understand now that request.form returns user-supplied information submitted in a form, which wont work for me because the information that i want to retrieve will be hardcoded into the html file under whichever tag that would allow this process to work. (currently tr -> td -> button).
the other methods either returned None or an some empty string, i believe.
also, i am wondering if maybe there is some piece of javascript code that ill need to use in addition to Flask as well? i hope that this is not an unrealistic expectation to ask this question! any suggestions would help greatly!
You can use ajax with jquery:
In the main filename.py, include a route like this, that access the parameters from the json response from the frontend. Also, provide a route that will render the HTML template:
#app.route('/recieve_data')
def get_id():
the_id = flask.request.args.get('button_id')
return "<p>Got it!</p>"
#app.route('/', methods=['GET', 'POST'])
def home():
return flask.render_template('filename.html')
In your HTML (stored in filename.html), utilize the code below:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<tr><td>
<button id="socks.shirt.pants" type='button'> dummy text here</button>
<div id='response'></div>
</td></tr>
</body>
<script>
$(document).ready(function() {
$("button").click(function(event){
var the_id = event.target.id;
$.ajax({
url: "/recieve_data",
type: "get",
data: {button_id: the_id},
success: function(response) {
$("#response").html(response);
},
error: function(xhr) {
//Do Something to handle error
}
});
});
});
</script>
</html>

Onclick write to database whithout refreshing

I've been working on a Flask application for a while.
Everything going pretty smooth because I was avoiding a problem. When writing to the database I always used a post ( that makes the page reloading ).
Not a big problem when posting forms etc.
Now I want a "i want help" button that makes a value true or false in the db.
Based on this value i would generate html that provides help.
But the button cannot make the page refresh. This is where i got stuck.
I only managed to get it working without writing to the db ( and storing it localy ).
Is there an obvious thing that i miss? or some Flask magic that gets it done.
The solution that I'm thinking about is posting to the db after leaving the page. Haven't got this working though.
Thanks in advance!
This example uses Ajax to send some data to the Flask back-end with jQuery and receive a response. It's very simple, but I marked the place where you'd handle the processing that you want the back-end to take care of after the user clicks your help button.
from flask import Flask, render_template_string, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template_string('''
<html>
<head>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.4.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#send_data').on('click', function() {
$.ajax({
url: "{{ url_for('data_post') }}",
method: "POST",
data: {
data: $('#data').val()
},
success: function(data) {
$('#response').html(data);
}
});
});
});
</script>
</head>
<body>
<input type="text" name="" id="data">
<button id="send_data">Send</button>
<br />
<p id="response"></p>
</body>
</html>
''')
#app.route('/data', methods=['POST'])
def data_post():
# handle your database access, etc.
return 'received'
if __name__ == '__main__':
app.run()
It's a simple index page with a textbox and button. Enter something into the textbox and click the button. You should see "received" on the page underneath the makeshift form, which is the echo from the back-end that the processing (in this example there isn't any) is done.
I'm also working on a Flask app currently, if you don't want to reload the webpage, you'll have to make an AJAX call. This can be easily done via jQuery.post() function. Also, you might need to setup a new route in Flask, so as to provide the required data to which the post function will make a request. To disable auto form submission, you can use:
$('form').submit(false);
And for posting manually and receiving data from server, you can use:
<button ... onclick="submitForm()">Submit</button>
And submitForm():
function submitForm()
{
$.post( url, { "data": "form-data" }).done(function (){...});
}
Hope this helps.

Python-Flask AJAX GET data does not display on HTML page

I have created a single page app using Python and Flask. The page has a "next" button. When the user clicks the "next" button I want to reload the page using data ('id2') that I send with the GET request.
Here's my problem: When I execute the GET request I can see that the AJAX data is being received by my Python controller function. But, the HTML page does not seem to refresh with the correct data (In the example below, "bar" is not passed to the HTML page.)
I believe that no new page is being sent to my browser. The output in my terminal window below only shows a GET request. Also, when I look at the network traffic in Chrome Dev tools, after I click the 'next' button, I only see a new get request, and no new page is sent to the browser.
Can someone please help me understand how to create a GET (or POST) request that triggers the server to serve a new HTML page that includes the data from the GET request?
Thanks!
My Python Controller:
#app.route('/', methods=["GET", "POST"])
def home_page():
print 'new page requested'
data = request.args.get('id2');
if data != None:
return render_template("index.html", article="foo")
else:
return render_template("index.html", article="bar")
My HTML/Javascript code:
<!DOCTYPE html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
</head>
<body>
<p>{{ article }}</p>
<button class="next" id="next">Next</button>
<script>
$("#next").click(function() {
$.ajax({
type: "GET",
url: '/',
data: {id2: "{{ article }}"}
});
});
</script>
</body>
Terminal Data:
new page requested
127.0.0.1 - - [17/Apr/2015 00:01:16] "GET /?id2=foo HTTP/1.1" 200 -
If you want to use AJAX to replace the entire DOM with the template being output from your Flask app you can simply do the following:
var nextArticle == 'foo';
$("#next").click(function() {
$.get("/?id2=" + foo, function(data) {
document.open('text/html');
document.write(data);
document.close();
// recreate binding for your $("#next") button
}
}

Categories