Why can't I post data to the flask server using ajax? nothing gets printed out - html

#app.route('/')
def index():
users = [[1],[2],[3]]
return render_template('index.html', users=users)
#app.route('/update', methods=['GET', 'POST'])
def update():
print(' post received ')
if request.method == 'POST':
print(request.form['idval']
return jsonify({'result': 'success'})
and this is my simple html
{% block body %}
<body>
{% for user in users %}
<td id='position{{user[0]}}' class='updateposition'></td>
<td id='amount{{user[0]}}' class='updateamount'></td>
{% endfor %}
<script src="http://code.jquery.com/jquery.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="{{ url_for('static', filename='app.js') }}"></script>
</body>
{% endblock %}
and here's my app.js file within static folder which contains the jquery
$(document).ready(function() {
setInterval(ajaxCall, 1000);
function ajaxCall(){
var positionIds = Array.prototype.slice.call(document.querySelectorAll('.updatecurrposition')).map(function ( element ) { return element.id;});
var amountIds = Array.prototype.slice.call(document.querySelectorAll('.updatepositionamount')).map(function ( element ) {return element.id;});
console.log(positionIds[0])
for (i = 0; i < positionIds.length; i++){
req = $.ajax({
url : '/update',
type : 'POST',
data : {idval : positionIds[i]}
});
}
}
and this example was taken from
https://github.com/PrettyPrinted/youtube_video_code/tree/master/2017/03/27/Using%20jQuery%20to%20Update%20a%20Page%20Without%20Refresh%20(Part%201%20of%202)/ajax_without_update
I've literally copied every single tutorials online and tried to implement it in my own (and most of the tutorials themselves fail in my computer for some reason)
and it just seems it can't get the data. I get a proper initial 200 response to get the html template but when the POST request does work, it only shows 304 redirect message, but nothing gets printed in the console
this perhaps seems to be the reason when I try to update the value upon receiving the data from the flask server, nothing happens. i.e.
req.done(function(data){
$('#'+positionIds[i]).text(data.result);
});
adding this right after req = $.ajax seems to change nothing

Does changing the td tags to something like p work? From tests I think that empty td tags aren't generated. I changed the tags and it was printing (to the console) successfully.

Related

Why do I get 404 error when calling Ajax Load Function in Django?

Picture 1 Picture 2 Picture 3 I am building a page in Django that first renders a blank page with a loading picture, and then calls an Ajax get function to one of my views. Once my Ajax get function succeeds, it is supposed to load one of my HTML files. I get a 404 error saying that the template cannot be found, but the template is in the same folder as my other file. Is my file path wrong?
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
</head>
{% extends "stocks_sites/base.html" %}
<!-- The loading image -->
{% block loader %}
<div id="loading">
<p>Loading</p>
</div>
<div id="articles">
</div>
<script>
// AJAX call when page has loaded
$(document).ready(function(){
$.ajax({
type: "GET",
url: "{% url 'stocks_sites:get_news_articles' %}",
success: function(response) {
const news_articles = response;
const posts = news_articles.posts;
const search = news_articles.search;
document.getElementById("loading").style.display = "none";
$("#articles").load("news_articles.html");
}
});
});
</script>
{% endblock loader %}

Why is Flask not loading images the second time I render a template?

I have made a ML model which I am deploying in a website using Flask. This is the code for it:
main.py
#imports
app = Flask(__name__)
def check(url):
#function to check whether the URL entered by user is Phishing or not and return the result
#app.route('/')
def home():
return render_template("home.html") #renders homepage template
#app.route('/phish/<url>')
def phish(url):
for i in range(0,len(url)):
if url[i]=="$":
url = url[:i]+"/"+url[i+1:] #changing url back to original
return render_template("phish.html", url=url)
#app.route('/safe/<url>')
def safe(url):
for i in range(0,len(url)):
if url[i]=="$":
url = url[:i]+"/"+url[i+1:] #changing url back to original
return render_template("safe.html", url=url)
#app.route('/', methods=['POST'])
def results():
url = request.form['url']
result = check(url)
for i in range(0,len(url)):
if url[i]=="/":
url = url[:i]+"$"+url[i+1:] #changing "//" to "$$"
if result==1 :
return redirect(url_for("phish", url=url))
else :
return redirect(url_for("safe", url=url))
if __name__ == '__main__':
app.run()
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- bunch of meta tags -->
<title>PhishLearn</title>
<link href="{{ url_for('static', filename='css/bootstrap.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/main.css') }}" rel="stylesheet"> <!-- for loading
css -->
</head>
<body>
<!-- body code -->
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
</body>
</html>
The code for phish.html and safe.html is also exactly same except for some changes in the body part.
Now when I initially run my main.py file the home page is loaded perfectly. But when I input a URL and click submit the page that is then rendered according to the result (phish or safe) does not display any image. Here are the screenshots of the pages:
Homepage
Result Page
As you can see when safe.html is rendered it does not shows any images. Can anyone tell me why this is happening and how to solve this issue?
I just use the src attribute of img tag to specify the path of file. Since all my html resources (css, js, images, etc.) are inside the static folder so I write src = "static/img/image-name.jpg"
That's your problem (as I kind of guessed).
When the URL in your browser is /phish/foople.blarp.quux, then static/img/image-name.jpg relative to that path is /phish/foople.blarp.quux/static/img/image-name.jpg which obviously 404s.
You need to
use the {% url_for("static", filename=...) %} form so Flask will deal with forming the correct static URL,
or alternately but less preferably (since changing the static files' root path will then require you to edit every template you have) use an absolute path /static/img/image-name.jpg.
or if you feel like using esoteric and often-forgot-about HTML features, set <base> and never worry about relative paths, but really please don't do that.

How can I iterate through each item in a database and display them in divs on my html page with django?

I have some code written to find the first post in the database and output it to my page, but I', not sure how to go about iterating through the database. I've done similar things before but this is my first time using django and bootstrap.
My view currently looks like this:
def gallery_view (request):
obj = GalleryPost.objects.get (id =1)
context = {
'object' : obj
}
return render(request, "gallery.html", context)
This works well enough for 1 object but as you can see it takes a set ID of 1, so I need to somehow iterate this to fetch every item from my DB and somehow output them properly.
View:
def gallery_view(request):
qs = GalleryPost.objects.all()
context = {
'objects' : qs
}
return render(request, "gallery.html", context)
html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for object in objects %}
<div>
{{object}}
</div>
{% empty %}
<p>No objects found</p>
{% endfor %}
</body>
</html>
Instead of .all() you can also use .filter() to filter the queryset.

How to add custom view in django adminlte?

I created an environment using pycharm & installed adminlte by git clone from https://github.com/app-generator/django-dashboard-adminlte.git. And installed adminlte3 , django3.1 & all requirements. Then run python manage.py runserver and registered a new user & was able to login ,view all pages, added new link to a html page. But I am unable to add view with jsonresponse to a button click on new page, geting Error 500 - Server Error.
My new html page is
{% extends "layouts/base.html" %}
{% block title %} Layout Boxed {% endblock %}
<!-- Element injected in the BODY element -->
{% block body_class %} sidebar-mini layout-boxed {% endblock body_class %}
<!-- Specific Page CSS goes HERE -->
{% block stylesheets %}
<!-- Google Font: Source Sans Pro -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Source+Sans+Pro:300,400,400i,700&display=fallback">
<!-- Font Awesome -->
<link rel="stylesheet" href="/static/assets/plugins/fontawesome-free/css/all.min.css">
<!-- Theme style -->
<link rel="stylesheet" href="/static/assets/css/adminlte.min.css">
<link rel="stylesheet" href="/static/assets/css/mapstyle.css">
<link rel="stylesheet" href="/static/assets/js/pages/gis/dist/map.css">
<style>
.map {
margin: 0;
padding: 0;
width: 900px;
height: 500px;
background:white !important;
border:1px solid #ccc;
}
</style>
{% endblock stylesheets %}
{% block content %}
<div class="content-wrapper">
<div id="lyrDiv"></div>
<div id="map" class="map"></div>
<button id="search">Search</button>
</div>
{% endblock content %}
<!-- Specific Page JS goes HERE -->
{% block javascripts %}
<!-- jQuery -->
<script src="/static/assets/plugins/jquery/jquery.min.js"></script>
<!-- Bootstrap 4 -->
<script src="/static/assets/plugins/bootstrap/js/bootstrap.bundle.min.js"></script>
<!-- AdminLTE App -->
<script src="/static/assets/js/adminlte.min.js"></script>
<!-- AdminLTE for demo purposes -->
<script src="/static/assets/js/demo.js"></script>
<script src="/static/assets/js/pages/map.js"></script>
<script src="/static/assets/js/pages/search.js"></script>
{% endblock javascripts %}
search.js
$( "#search" ).click(function() {
$.get('/search/',{'csrfmiddlewaretoken':csrftoken},function(data){
alert(data); // here getting Error 500 - Server Error
});
});
I added below line to /django-dashboard-adminlte/app/urls.py
re_path(r'^search/$', search.spatial_srch, name='search'),
and search.py
from app.models import *
from django.views.decorators.csrf import csrf_exempt
from django.http import JsonResponse
#csrf_exempt
def spatial_srch(request):
data= Demotable.objects.all()
searchArr = []
output = {}
for c in data:
searchArr.append({'type': 'Feature', 'properties': {'id':c.id,'name': str(c.name)},'geometry': {'type': 'Point', 'coordinates': [c.the_geom.x, c.the_geom.y]}})
output = {'type': 'FeatureCollection', 'features': searchArr}
return JsonResponse(output)
When I click on the 'Serach' button the request is not going to the view search.py What is wrong in my code ? what configuration did I miss?
The post shows
The Error 500 shows only adminlte Error page. Nothing more
The problem is in the (not so nice) way they generate the error. It's anti-pattern hell there, but in short it means there's an except thrown in either:
finding the template
loading the template
or rendering the template
and they catch it and don't let you see what happened. Not very nice code and you're have to modify that file to even begin debugging it:
#login_required(login_url="/login/")
def pages(request):
context = {}
# All resource paths end in .html.
# Pick out the html file name from the url. And load that template.
try:
load_template = request.path.split('/')[-1]
html_template = loader.get_template( load_template )
return HttpResponse(html_template.render(context, request))
except template.TemplateDoesNotExist:
html_template = loader.get_template( 'page-404.html' )
return HttpResponse(html_template.render(context, request))
# Remove or comment these lines:
#except:
#
# html_template = loader.get_template( 'page-500.html' )
# return HttpResponse(html_template.render(context, request))
Also I'm not sure this the specific spot where the error is generated, they might be doing similar things in other places.
Edit
This is very .... unprofessional code:
# Matches any html file
re_path(r'^.*\.*', views.pages, name='pages'),
No, it doesn't not match any "html" file - it matches everything cause they don't get regular expressions:
^ - start of string
.* - anything or nothing
\.* - >>>zero<<< or more dots
Result: \.* is ignored as it is irrelevant so it matches everything and if you placed your re_path below it, it will never be consulted, because Django uses first match wins approach.
So your url matches theirs, which then routes it to pages view:
load_template = request.path.split('/')[-1]
Since request.path is '/search/', '/search/'.split('/')[-1] gives the empty string and that creates your problem.
I highly suggest fixing their url path:
# Matches any html file
re_path(r'\.html$', views.pages, name='pages'),
Or put your re_path above theirs.

Unable to render PIL object base64 image on template

I'm trying to display a PIL object after converting to base64.
I'm getting the base64 value in the src tag but the response is not rendered even after decoding
import base64
import io
def newrules(request):
pic = con(select.fname)
print(pic)
buffered = io.BytesIO()
pic.save(buffered, "PNG")
img_str = base64.b64encode(buffered.getvalue())
template_code = """
{% load static %}
<!DOCTYPE HTML>
<html>
<body>
{% block pagecontent %}
<div>
<img src="data:image/png;base64,{{ img_str }}">
</div>
<div>
{{ img_str }}
</div>
</body>
{% endblock %}
</html>
"""
template = engines['django'].from_string(template_code)
return HttpResponse(template.render(context={'img_str': img_str}))
HTML souce code
terminal API call responses
Template rendered
Any help will be highly appreciated.
base64.b64encode(buffered.getvalue()) returns a byte class object. It needs to be converted to a string before passing it to a template. It can be done as follows:
img_str = base64.b64encode(buffered.getvalue()).decode('ascii')