Using Ajax with Django to call backend and display result - javascript

I am taking user input and sending it to Django backend for some text processing. After performing backend operation I want to display results.
I tried but as I am new with ajax,I am not sure where I am making mistake. Can anyone please give me correct way of using ajax for this operation? I appreciate if you can give link to any good reference document.
Current issue - When I click on submut button it removes input text area.
My html report.html -
{% extends 'base.html' %}
{% block content %}
<h1>StopWordsRemoval</h1>
<script type='text/javascript'>
$(document).ready(function(){
$(form).on('submit', function(event){
$.ajax({
url: 'stopwordsremoval/(?P<document1>.+)'
type: 'POST',
data: this.serialize(),
});
});
});
</script>
<div>
<form method = "post" >
{% csrf_token %}
{{ form}}
<button type="submit">stopwordsremoval</button>
</div>
</form>
<div >
<ul>
<li>{{ naturallanguageprocessing }}</li>
</ul>
<a href="{% url 'stopwordsremoval' %}" </a>
<style>
div {
width: 1000px;
border: 5px solid green;
padding: 10px;
margin: 10px;
}
</style>
</div>
</div>
{% endblock %}
urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'stopwordsremoval/$', views.stopwordsremoval.as_view(), name='stopwordsremoval'),
url(r'stopwordsremoval/(?P<document1>.+)/$',
views.ReportDetails.as_view(), name='report_details'),
]
forms.py
from django import forms
class ReportForm(forms.Form):
#pdb.set_trace()
text = forms.CharField(widget=forms.Textarea(attrs={'rows': 5, 'cols': 100}))

<script type='text/javascript'>
$(document).ready(function(){
$(button).on('click', function(event){
var form = $(form).serialize()
$.ajax({
url: 'stopwordsremoval/(?P<document1>.+)' // this will not work
type: 'POST',
data: form,
});
});
});
</script>

Related

how do I use a button to display <div> in django template?

results.html
{%if searched_user %}
{{searched_user}}
<button id=likedsongsbutton>View liked songs</button>
<div>
{% for each_searched_user in searched_user %}
<br id="likedsongs"/>{% for liked_songs in each_searched_user.liked_songs.all %}{{liked_songs}}
<br/>
{% endfor %}
{% endfor %}
{% endif %}
{% endblock %}
</div>
<script>
document.querySelector("#likedsongsbutton").addEventListener(onclick, )
</script>
views.py
def results(request):
if request.method == "GET":
search_query = request.GET.get("username")
searched_user = UserProfile.objects.filter(
user__username__contains=search_query
)
return render(
request, "results.html", {
"searched_user":searched_user
})
My question is how do I make the <div> show only when the button is clicked? I do not know what function to pass in the EventListener
If you give your change you div to have an id of myDiv and set the display to be None, you can pass the following lambda in as the second parameter.
() => {document.getElementById("myDiv").style.display = ""}
While the div looks like:
<div id="myDiv" style="display: none"></div>
I also think you should change it from onclick, to "click". Here is a complete example:
<button id=likedsongsbutton>View liked songs</button>
<div id="myDiv" style="display: none; background: blue; height: 100px; width: 100px;"></div>
<script>
document.querySelector("#likedsongsbutton").addEventListener("click", () => {
document.getElementById("myDiv").style.display = ""
});
</script>

Django App Not Communicating with JavaScript Code Block

I have a Django application that accepts an Elasticsearch query in a form and produces a downloadable report. An earlier iteration worked great, but we decided to add a component that checks every ten seconds if the report is done being created. Our ultimate goal is to have it check repeatedly for the completed report (and tell the user the report is still processing if not complete), and then either add a button to download the report or just have it automatically begin downloading.
However, my application doesn't seem to be calling on the javascript block I have in my form.html. When I run this, it says {"file_created": False} until I manually refresh myself, then it switches to True. I tried the code commented out in check_progress (which is basically what my code in form.html does...) but it returned an error.
How do I make them communicate? What am I missing?
views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse, JsonResponse, HttpResponseRedirect
import os
import threading
from .forms import QueryForm
from .models import *
#login_required
def get_query(request):
if request.method == 'POST':
form = QueryForm(request.POST)
if form.is_valid():
query = form.cleaned_data["query"]
t = threading.Thread(target=generate_doc, args=(query,))
t.start()
return HttpResponseRedirect('/check_progress/')
else:
return HttpResponse("Your query does not appear to be valid. Please enter a valid query and try again.")
else:
form = QueryForm()
return render(request, 'audit_tool/form.html', {'form': form})
#login_required
def check_progress(request):
"""
Returns whether document generation is complete or in progress
"""
# check if file exists, return response as a JSON
# how to integrate with js code in html to continuously check and refresh
# only shows true when refreshed; how to talk to html??
file = "/report.docx"
data = {
"file_created": os.path.exists(file)
}
# if os.path.exists(file):
# response = generate_doc(query)
# return response
# else:
# return HttpResponseRedirect('/check_progress/')
# this does not work, "10.168.83.100 redirected you too many times.
# Try clearing your cookies.
# ERR_TOO_MANY_REDIRECTS"
return JsonResponse(data)
#login_required
def return_doc(request):
"""
Returns file response upon user request, or error message if something goes wrong
"""
response = generate_doc(query)
return response
form.html
<!-- templates/django_audit/form.html -->
{% extends 'base_login.html' %}
{% block javascript %}
<script>
var checkInterval = setInterval(isFileComplete, 10000); //10000 is 10 seconds
function isFileComplete() {
$.ajax({
url: '/check_progress/',
type: 'GET',
data: {
'file_created': 'True'
},
dataType: 'json',
success: function (data) {
if (data.exists) {
alert("Your file is ready to download!");
clearInterval(checkInterval);
} else {
alert("Your report is still being created, please hold.");
}
}
});
}
</script>
{% endblock %}
{% block title %}Form{% endblock %}
{% block content %}
<p><br></p>
<p><br></p>
<div class="alert alert-primary" role="alert">
<b>Instruction:</b>
{% load crispy_forms_tags %}
<!-- form action="/report/" method="post" onsubmit="this.submit(); this.reset(); return false; -->
<form action="/report/" method="post" onsubmit="this.submit(); this.reset(); return false;">
{% csrf_token %}
{{ form|crispy }}
<input type="submit" value="Submit">
</form>
</div>
{% endblock %}
core/urls.py
from django.contrib import admin
from django.urls import include, path
from django.views.generic.base import TemplateView
from django.conf import settings
from django.conf.urls.static import static
from audit_tool import views
urlpatterns = [
path('admin/', admin.site.urls),
path('accounts/', include('django.contrib.auth.urls')),
path('form/', include('audit_tool.urls')),
path('report/', include('audit_tool.urls')),
path('check_progress/', views.check_progress, name='check_progress'),
path('', TemplateView.as_view(template_name='home.html'), name='home'),
] + static(settings.STATIC_URL, document_root=settings.STAT)
audit_tool/urls.py
from django.urls import path
from . import views
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('', views.get_query, name='form'),
] + static(settings.STATIC_URL, document_root=settings.STAT)
base_login.html
<!-- templates/base.html -->
<!DOCTYPE html>
<html>
<html lang="en">
{% load static %}
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="{% static 'bootstrap/css/bootstrap.min.css' %}">
<link rel="shortcut icon" href="link/to/company/iconicon.ico" type="image/vnd.microsoft.icon" />
<title>Audit Report Tool</title>
</head>
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<a class="navbar-brand" href="#">Dept</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item active">
<a class="nav-link" href="../">Home</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../admin">Admin</a>
</li>
</ul>
</div>
</nav>
<div class="container">
<div class="row justify-content-center">
<div class="col-8">
<hr class="mt-0 mb-4">
<img src="{% static "logo.png" %}" alt="Company Logo" align="left"></img>
<img src="{% static "logo.png" %}" alt="Dept Logo" align="right" width="140" height="140"></img>
<h1 align="center"><font size="6"> Audit Report Tool</font></h1>
</div>
</div>
</div>
<body>
<main>
{% block content %}
{% endblock %}
</main>
</body>
</html>
Your key is data.file_created, not data.exists in if (data.exists) { line. And that sending of data: {'file_created': 'True'}, get rid of that in your javascript - you're not querying request for anything in your view, as, for example, the name of the file, so you don't need to fill that data.
Also the following:
file = "/report.docx"
data = {
"file_created": os.path.exists(file)
}
It implies that report.docx is going to be saved in the root of the filesystem, that's not going to happen. Use something like
from django.conf import settings
os.path.join(settings.BASE_DIR, "../upload/", "report.docx")
Also ,you may provide the part of base_login.html where that {% block javascript %} is placed.

Javascript inside Jinja "for" loop

I'm coding an app in Python Flask and I'm building interactive Like buttons with Javascript.
Here's my route:
#app.route('/jquery')
def jquery():
posts = Post.query.all()
return render_template('jquery.html', posts=posts)
And in the jquery.html template I have:
{% for p in posts %}
{% if p.upvotes %}
{% set pupvotes = p.upvotes %}
{% else %}
{% set pupvotes = 0 %}
{% endif %}
<p>{{ p.author.username }} says: <b>{{ p.body }}</b> <button id="
{{ p.id }}" onclick="document.getElementById('{{ p.id }}').innerHTML = {{
pupvotes }} +1 + ' Likes'">{{ pupvotes }} Likes</button></p>
{% endfor %}
Everything actually works this way, but I would like to save the results of +1 likes clicks and transfer them to a Python variable so that I can add it to the database and the updated Like numbers show up on the page after refresh.
I tried to use JavaScript function this way:
<script>
function myF1() {
document.getElementById('{{ p.id }}').innerHTML = {{ pupvotes }} +1 + '
Likes';
}
</script>
and:
onclick="myF1()"
But then only the last Like on the page gets updated with click, no matter which Like button I click.
OK, I've made it work:
Here's our Flask route:
#app.route('/ulk')
def ulk():
ppp = request.args.get('p', 0, type=int)
lpost = Post.query.filter_by(id=ppp).first()
lpost.upvotes += 1
db.session.commit()
return jsonify(result=ppp)
And here's our HTML page with some jQuery:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<body>
<script type=text/javascript>
$(function() {
$('a#like').bind('click', function() {
$.getJSON('/ulk', {
p: pid
}, function(data) {
$("#result2").text(data.result);
});
return false;
});
});
</script>
<br/><br/>
{% for p in posts %}
{% if p.upvotes %}
{% set pupvotes = p.upvotes %}
{% else %}
{% set pupvotes = 0 %}
{% endif %}
<p>{{ p.author.username }} says: <b>{{ p.body }}</b>
<a href="#" id=like>
<button id="{{ p.id }}" onclick="pid={{ p.id }};pvts = {{ pupvotes }} +1;myF1();">{{ pupvotes }} Likes</button>
</a>
</p>
<script type=text/javascript>
function myF1() {
$( "#" + pid ).text(pvts + ' Likes');
$('#' + pid).on('click', function() {
$(this).prop('disabled', true);
});
}
</script>
{%endfor%}
<br/>
<span id=result2>...</span>
</body>
</html>
You are close, however, as #MartijnPieters pointed out, you still need to communicate with the backend to update the number of likes for the post. To do so, slightly change your HTML to include a button to update the likes with a class and id. The id will be the same as the post id, and the class will be generic. Then, utilize jquery with ajax after creating a script.
First, in the Python backend, create a route to handle the updating of the likes for a post:
#app.route('/update_like')
def update_likes():
_id = int(flask.request.args.get('post_id'))
#Do something to update the database
return flask.jsonify({'success':'True'})
I suggest returning a jsonified response so that you can handle errors that may occur, such as a user liking a post twice. If you discover that that is the case, then you could return flask.jsonify({'success':'False'}) and handle that accordingly in the frontend.
Then, in the HTML:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</head>
<div class='post_wrapper'>
{%for p in posts%}
<div id='post_{{post.id}}'>
<p>{{p.author.username}} says:</p>
<p>{{p.body}}</p>
{%if p.upvotes%}
<button class='upvote' id='upvote_{{p.id}}'>Like <span id='upvotes_{{p.id}}'>{{p.upvotes}}</span></p>
{%else%}
<button class='upvote' id='upvote_{{p.id}}'>Like <span id='upvotes_{{p.id}}'>0</span></p>
{%endif%}
</div>
{%endfor%}
</div>
<script>
$(document).ready(function(){
$('.post_wrapper').on('click', '.upvote', function(){
var post_id = this.id.match('\\d+');
$.ajax({
url: "/update_like",
type: "get",
data: {post_id: post_id},
success: function(response) {
if (response.success === 'True'){
var like_val = parseInt($('#upvotes_'+post_id).text()) + 1;
$('#upvotes_'+post_id).text(like_val.toString());
}
else{
alert('You already liked that post!');
}
}
});
});
});
</script>
</html>

Django - ajax call for loading page not working

I need really help..
I'm not good at front-end and I'm very confused with Ajax.
I'm trying to do an Ajax call for when I click on a button of my table so when I hit that button my ajax should show my animation .gif so the user should know that the page is loading.
my template:
<style>
.ajaxProgress{
display:none;
text-align: center;
}
</style>
<div id="output">
<div class="ajaxProgress">
<h3>Please wait..</h3>
<img src="{% static 'img/ajax.gif' %}" alt="loading"/>
</div>
</div>
{% for item in qs %}
<tr>
<tbody>
<td
a id="mqtt" class="btn btn-xs btn-info" title="mqtt" href="javascript: startAjax(){% url 'start_mqtt' item.id %}"><span class="fa fa-signal"></span> </a> </td>
</tbody>
</tr>
{% endfor %}
</table>
<script>
function startAjax() {
$('.ajaxProgress').show();
$.ajax({
type: "GET",
dataType:"json",
async: true,
data: { csrfmiddlewaretoken: '{{ csrf_token }}' },
success: function(json){
$('#output').html(json.message);
$('.ajaxProgress').hide();
GetRating(json.message);
}
})
}
</script>
Basically what I need is when I hit on the button should start my .gif but nothing happens....
var $loading = $('.ajaxProgress').hide();
$(document)
.ajaxStart(function () {
$loading.show();
})
.ajaxStop(function () {
$loading.hide();
});
I like to use this way

Don't pick up Django form value to javascript function

I'm trying to pick up RadioSelectBox value from my Django form to my template with a javascript part. But I don't overcome to get this variable and put it in my template.
I've a very simple form :
def ChoiceTheme(request) :
if request.method == 'POST':
form = ThemeForm(request.POST or None)
if form.is_valid():
theme = form.instance.favorite_theme
print theme
post = form.save()
return HttpResponseRedirect(reverse('accueil'), {"theme":theme})
else:
form = ThemeForm()
context = {
"form":form,
}
return render(request, 'Theme.html', context)
I get exactly the good field value with print theme.
But I want to place this variable in my html template :
{% block content %}
<style>
ul li {
list-style: none;
}
</style>
<div class = "col-sm-8">
<form class = "form" method='POST' action=''> {% csrf_token %}
<h3> <span class="glyphicon glyphicon-file"></span> Choix du thème DatasystemsEC </h3>
<br></br>
{{ form }}
<br></br>
<button> Valider le thème </button>
<script>
theme = "{{ }}"
$(function() {
$('button').click(function() {
alert("Vous avez choisi le thème : " + theme);
});
})(jQuery);
</script>
</form>
</div>
{% endblock content %}
I have theme = {{ theme }} but my alert window just display :
Vous avez choisi le thème :
Do you have any idea ? I'm very sily on this point, because I don't see the way ..
To extract the theme choice in django you would have to do an ajax request similar to this:
$(function() {
$('form').submit(function (event) {
event.preventDefault();
$.ajax({
url: "/choicetheme",
data: $('form').serialize(),
type: 'post',
success: function (data) {
alert(data.theme);
}
});
});
})(jQuery)
However you can also extract the choice before sending it to django in javascript but then you need to know what element are in the form IE the option element where you selected your theme.

Categories