FLASK - AJAX GET data from database - javascript

I am making a "write anything here" webpage where users can write anything in a textbox then post it and it is visible to everyone. It worked fine till I found out that when any user writes and submits, all the others have to refresh the page so as to get the new data from database. So a solution to this was to call ajax continuously in some intervals. This would check if there are new entries in the table. If yes, then it would render it to the html without refreshing the whole page. Now I am pure ajax noob and after hours of research I am unable to find out how to do it.
Here is the html code
<div id="textArea">
<form action="http://127.0.0.1:3000" method="POST">
<br>
<textarea minlength="3" name="comment" placeholder="Enter Text Here.." required></textarea>
<input id="postButton" type="submit" name="" value="POST">
</form>
</div>
</div>
<div class="show">
{% for item in data %}
<div id="auto" class="disPost">{{item[0]}}</div>
{% endfor %}
</div>
Here the textarea is in a form and it submits the text to database via flask server.
Also, all the comments that users wrote are shown in "div.show"
Now the flask code is like this
#app.route('/', methods = ['POST', 'GET'])
def home():
if request.method == 'POST':
post = request.form["comment"]
myquery = "select p_id from posts order by p_id desc limit 1"
mycursor.execute(myquery)
new_p_id = mycursor.fetchone()[0] + 1
myquery = "select exists(select * from posts where p_des=%s)"
rec_tup = (post,)
mycursor.execute(myquery, rec_tup)
if mycursor.fetchone()[0]==0:
myquery = "insert into posts values(%s, %s)"
rec_tup = (new_p_id, post)
mycursor.execute(myquery, rec_tup)
mydb.commit()
mycursor.execute("select distinct p_des from posts order by p_id desc")
data = mycursor.fetchall()
return render_template("homepage.html", data=data)
"mydb" is the connector & "mycursor" is the connector's cursor
Now I am stuck somewhere in how to call AJAX function. I am not able to write beyond this ..
$(document).ready(function() {
setInterval(function() {
$.ajax({
url: '',
type: 'GET',
data: //something must be here,
success: function(data) {
//here "div" must be added to the "show" class - that is comment of other users
}
})
}, 3000);
});
I know that I have to do something like this but am literally not able to solve it.
I know this is not good question and I must look at tutorials first. But believe me I had it all. I am not able to solve this problem at all.
Thank you for seeing this :)

I did this on my latest project, you can try it too. But make sure to refresh only div element you want the data show, not all the page.
$(document).ready(function() {
function getData(){
$.ajax({
url: '',
type: 'GET',
data: //something must be here,
success: function(data) {
//here "div" must be added to the "show" class - that is comment of other users
}
});
}
getData();
setInterval(function() {getData()},2000);
});

Related

Get user input and output Flask and HTML

I'm trying to develop a web-app with Flask and HTML and right now I need to get the user input, pass it to the Python back-end, execute a function and return its output, placing it inside an HTML element. I also want this to happen without refreshing the HTML page.
How can I do this?
Bellow I have the code that I've developed so far but it's not working correctly:
My HTML:
<div id="ThroughputRate" class="data_entry">
<form action="{{ url_for('background_check_throughputrate') }}" method="post">
<input name="throughput_rate_text" class="input_box">
<input id="checkThroughputRate" type="submit" class='new-button-data' value="Check Throughput Rate">
<output name="throughputRateResult" class="result_box" ></output>
</form>
</div>
My Flask backend:
#app.route('/background_check_throughputrate', methods=['GET', 'POST'])
def background_check_throughputrate():
if request.method == 'POST':
text = request.form['throughput_rate_text']
processed_text = str(text)
throughput = transition_throughput_rate(processed_text)
return jsonify(throughput)
My HTML (continuation to get the output of the function executed on Flask):
<script type=text/javascript>
$(function() {
$('a#checkThroughputRate').bind('click', function() {
$.getJSON('/background_check_throughputrate', function(data) {
console.log(data);
document.getElementById('throughputRateResult').innerHTML = data;
});
return false;
});
});
</script>
The idea behind my execution is that the user uses the first snippet of code (in HTML) to insert the input, this input is passed onto the second snippet of code (in flask) and finally, the output of the function is passed onto the last snippet of code (in JS inside HTML) so that it can be displayed on the corresponding HTML element.
So far, the input is being correctly processed inside flask but the issue is that when the function returns the jsonify, it appears on the screen, instead of sending it into the frontend. What am I doing wrong?
Thank you all
$.getJSON is designed to load the JSON data from endpoint using GET request, however, your Python code example responds to only POST requests.
Here is the working code:
HTML
<div id="ThroughputRate" class="data_entry">
<form action="{{ url_for('background_check_throughputrate') }}" method="post" id="throughputRateForm" enctype="multipart/form-data">
<input name="throughput_rate_text" class="input_box">
<input id="checkThroughputRate" type="submit" class='new-button-data' value="Check Throughput Rate">
<output id="throughputRateResult" class="result_box" ></output>
</form>
</div>
Python
#app.route('/background_check_throughputrate', methods=['GET', 'POST'])
def background_check_throughputrate():
if request.method == 'POST':
text = request.form['throughput_rate_text']
processed_text = str(text)
throughput = transition_throughput_rate(processed_text)
return jsonify(throughput)
JavaScript
<script type="text/javascript">
$(function () {
$('#throughputRateForm').on('submit', function (e) {
e.preventDefault();
var form = $(this)[0];
var formData = new FormData(form);
$.ajax({
url: '/background_check_throughputrate',
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: function (data) {
console.log(data);
document.getElementById('throughputRateResult').innerHTML = data;
}
});
});
});
</script>
Also, this code blindly trusts the user input and displays it on the webpage which can result to Cross-Site Scripting (XSS) and that is not good!
Avoid using innerHTML property when displaying user input, because it can be used to inject malicious HTML tags (e.g. <script>), i would highly recommend using innerText property instead.

Displaying the result of ML model on Web page

I am exploring RESTful Flask API and as a learning I have created a small web form in HTML. Please see below the code for HTML.
<!DOCTYPE html>
<html>
<h2>User Input</h2>
<body
<script>
src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js">
</script>
<script src="/static/js/predict.js"></script>
<p>Please enter the Power prices per unit</p>
<form method="get" action='/predict' target ="_blank"
enctype="multipart/form-data">
New Value - 1:<br>
<input type="number" id="New_val_1">
<br>
New Value - 2:<br>
<input type="number" id="New_val_2">
<br><br>
<button id="btnpredict" type="button">Predict</button>
</form>
<p>If you click the "Submit" button, the form-data will be sent to a page
called "/action_page.php".</p>
</body>
</html>'
Please see below the code for predict.js. This is a JQuery AJAX
$(function(){
$('#btnpredict').click(function(){
$.ajax({
url: '/predict',
data: JSON.stringify({userInput: uInput})
type: 'GET',
contentType: 'application/json',
success: function(response){
("#results").text(response.results);
},
error: function(error){
console.log(error);
}
});
});
});
And finally, the app.py code where the above HTML is getting rendered and upon receiving the the values passed on forms ML model is used.
from flask import Flask, redirect, request, render_template,json, Response
import statsmodels.api as sm
import numpy as np
from sklearn.externals import joblib
app = Flask(__name__)
#app.route('/')
#app.route('/home')
def home():
return render_template('index.html')
#app.route('/predict', methods = ['GET'])
def predict():
if request.method=='GET':
X_value_new_1 = request.values.get('New_val_1')
X_value_new_2 = request.values.get('New_val_2')
X_1,X_2 = X_value_new_1,X_value_new_2
testData = np.array([X_1,X_2]).astype(np.float).reshape(-1,1)
testData=sm.add_constant(testData)
pred = Regression_model.predict(testData)
dump = json.dumps({'prediction':list(pred)})
resp = Response(dump,mimetype='application/json')
return resp
return None
def load_model():
global Regression_model
Regression_model = joblib.load('E:/model_file_save')
if __name__ == "__main__":
print("**Starting Server...")
load_model()
app.run(debug=True)
Now the problem:
When I click on Predict button nothing happens. However, if on the address-bar if I write the 'http://localhost:5000/predict?New_val_1=1000&New_val_2=2000' then I get the correct prediction values in JSON format.
How to fix this issue? Is there any problem in JQuery?
Please help.
Best
AR
Read textbox values e.g. $("#tag").val() and concate with ajax url e.g.
predict?New_val_1=1000&New_val_2=2000'
and remove data property. You can also pass values using data property see below link for example.
https://www.codeproject.com/Questions/870797/How-to-pass-textbox-value-to-other-page-using-Jque

How can I improve my Ajax?

I'm trying to figure out if what I'm doing is the right way. I have a comment form and when it gets clicked I'm appending the comment into a div element through Ajax. When the page is refreshed then of course that would disappear and instead of it I have a foreach loop that runs and echos the comments. Since they both have the same CSS attributes they look the same to the user. The reason I'm doing it this way is because the foreach loop gets updated only after a refresh. Is there a better way? Can I update the page directly from the database without refresh? I basically need that every time a user clicks on the comment button that the foreach loop will run again but I couldn't find how to do it. I feel like I'm covering a gun shot with bandage the way I do it at the moment.
Loop:
#foreach($comment as $comments)
#if($comments->image_id == $image->id)
<div id="{{$comments->id}}" class="col-md-5 ajaxrules">
<div class="deletecomment">
<i class="fa fa-trash-o"></i>
</div>
<div class="col-md-2">
<img src="{{$comments->user_avatar}}" class="img-circle buddy">
</div>
<div class="hello col-md-10">
<h4>{!! $image->user_name !!}</h4>
<p class="left">{!!$comments->body!!} </p>
</div>
</div>
#endif
#endforeach
//Where I append the comments through Ajax until the refresh that replaces it with the loop
<div class="man">
</div>
Ajax:
<script>
$(document).ready(function(){
$('.send-form').click(function(e){
e.preventDefault();
var username = "{{ $username }}";
var one = $('textarea[id="{{$image->id}}"]').val();
var value = "{{$image->id}}";
var begin = '<div class="col-md-5 addavatar">'+'<div class="deletecomment">'+'<i class="fa fa-trash-o">'+'</i>'+'</div>'+'<div class="col-md-2">'+'<img src="{{$profile}}" class="img-circle">'+'</div>'+'<div class="hello col-md-10">'+'<h4>' + username +'</h4>'+'<p>'+one+'</p>'+'</div>'+'</div>';
if(one.length > 0){
console.log(username);
$('textarea[id="{{$image->id}}"]').val('');
$.ajax({
url: 'comment',
type: "post",
beforeSend: function (xhr) {
var token = $('meta[name="csrf_token"]').attr('content');
if (token) {
return xhr.setRequestHeader('X-CSRF-TOKEN', token);
}
},
data: {'id': value, 'comment': one},
success:function(data){
$( ".man" ).append([begin]);
},error:function(){
console.log("error!!!!");
}
});
}
});
});
</script>
You are killing yourself.
Manipulate the DOM via javascript code like you do it's really hard work!
You are not suppose to write html inside javascript strings, there must be another way!
And there is... Welcome to AngularJS!
In angular you can write your html and assign a javascript controller to it, perform ajax request and after the ajax complete you can bind the returned data to the html automatically! That means the angular refresh your html and do all the work for you. Even perform loop of let's say, row in a table, etc...

How to ajaxify writing short messages like on facebook

I have one text field where user can write short message (like status on g+ or fb) bellow that field I have a list where that messages need to be displayed. When user submit that message it is stored in database, after that I refresh whole View. This is how I display that list:
#foreach (var m in #Model.Messages){
<div>
<p>#m.Author</p>
<p>#m.Text</p>
</div>
}
Now I wan't to make better user experience. I wan't to add that message without refreshing while View. I know that I have to use JQuery, Ajax etc. but I have searched on the google and can't find any good tutorial or example for ASP MVC / Razor and this like feature. Can somebody give me some direction?
Typing asp.net mvc ajax jquery in google usually yields sufficiently enough results. But anyway here's what you could do. Assuming you have a text field where the users will type their messages:
#using (Html.BeginForm("AddMessage", "Messages", FormMethod.Post, new { id = "addMessageForm" }))
{
#Html.TextBoxFor(x => x.Author)
#Html.TextAreaFor(x => x.Text)
<button type="submit">Add message</button>
}
you could AJAXify this form:
$(function() {
$('addMessageForm').submit(function() {
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function(result) {
$('#messages').append(result);
}
});
return false;
});
});
and finally you would have a controller action which will perform the actual adding of the message to the database:
[HttpPost]
public ActionResult AddMessage(MessageViewModel message)
{
// TODO: add the message to the database
return PartialView("~/Views/Messages/DisplayTemplates/MessageViewModel.cshtml", model);
}
and a corresponding display template (~/Views/Messages/DisplayTemplates/MessageViewModel.cshtml):
#model MessageViewModel
<div>
#Html.DisplayFor(x => x.Author)
#Html.DisplayFor(x => x.Text)
</div>
and the list of messages will be shown using display templates and not using loops:
<div id="messages">
#Html.DisplayFor(x => x.Messages)
</div>

AJAX post failing XMLHttpRequest check in Django view

I have a simple html page which renders with a number of nearly identical forms for the user to submit. Upon submit, the view is intended to add a row to the database, recreate the list of forms with slightly updated data, and send it back to the browser ('/route/complete/' maps to add_completed_route_view in urls.py).
This works perfectly the first time. Once the page has been redrawn with the new list of forms, however, the next submit will fail the request.is_ajax() test I have in the view. That causes it to skip to request.REQUEST['next'] and subsequently to home_view.
I've commented it out below, but I've also tried appending c['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest' to the view but it hasn't helped.
I'm looking for help in ensuring that the headers continue to have the appropriate XMLHttpRequest param while the user submits through AJAX. Code is below, and help is much appreciated.
script.js
<script>
$(document).ready(function() {
$(".doneForm").submit(function() {
var route_id = $(this).find('input[name=route_id]').val()
var next = $(this).find('input[name=next]').val()
var reqData = {route_id:route_id,next:next}
$.ajax({
type: "post",
url: "/route/complete/",
data: reqData,
success: function(data) {
$("#routeTable").html(data);
}
});
return false;
});
});
</script>
and
template.html
<div id="routeTable">
{% for route in route_list %}
<div id="routeDone">
<form class="doneForm" action="/route/complete/" method="post">
<input type="hidden" name="route_id" value="{{ route.route_id }}" />
<input type="hidden" name="next" value="{{ request.get_full_path }}" />
<input type="submit" value="Done" class="doneButton" />
</form>
</div>
{% endfor %}
</div>
and
views.py
def add_completed_route_view(request):
if request.method == 'POST' and request.user.is_authenticated():
add_completed_route(request)
if request.is_ajax():
wall_slug = get_wall_slug_from_route_id(request.REQUEST['route_id'])
c = get_context_for_wall_page(request, wall_slug)
# c['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
return render_to_response('m/js_route_table.html', c, context_instance=RequestContext(request))
else:
return HttpResponseRedirect(request.REQUEST['next'])
else:
return HttpResponseRedirect(reverse('home_view'))
The problem is that once the Ajax is completed, it replaces the original form with a new one - and this one no longer has the javascript event handler attached, so the next time the form submits via the normal POST method.
Luckily, jQuery has a couple of methods that handle this for you - live and delegate. So instead of $(".doneForm").submit(function() ..., do this:
$(".doneForm").live("submit", function() {...

Categories