Removing query string from a view in Django - javascript

I have a page called controlpanel, where I can start/stop scripts. When the button for start and stop scripts is pressed, it return the same page with button color changed and I want to delete query string.
view.py
def controlpanel(request):
data = {'paypal': paypal_, 'cpu': cpu_usage, 'active': active_task ...}
return render(request, 'admin/controlpanel.html', context=data)
def startapp(request):
if request.META['QUERY_STRING']:
#... start scripts etc..
request.META['QUERY_STRING'] = False
return controlpanel(request)
the function return controlpanel with query string... (127.0.0.1:8000/startapp?run=True but I only want 127.0.0.1:8000/controlpanel)
controlpanel.html
<div>
{% if active %}
<button onclick="f()" class="btn btn-md btn-success">Start</button>
{% else %}
<button onclick="f()" class="btn btn-md btn-warning">Start</button>
{% endif %}
</div>
<script>
function f() {
let a = null;
if ('{{active}}' === 'True') {
a = 'stop'
} else {
a = 'start'
}
window.location.href = "/startapp?run=" + a;
}
</script>

You could use Django's redirect to return the URL without the query parameters.

Related

Update single row of table in template page using ajax in Django

I am working on Django project and I have no idea of ajax that how to implement it. The scenario is my db contains a table name "demo" which contains the column stat_id. My database contains the following details:
table name = demo
id int primary key NOT NULL,
stat_id int(11) NOT NULL #value is 1
Now, the scenario is that I am getting the stat_id value from database and its purpose to show the running and complete button. If python script is running then it will display the running button and if python script has executed it will display the completed button.
status.html:
<td>
<form action = "/modules" method="get">
{% if status == 1 %}
{% csrf_token %}
<button link="submit" class="btn btn-default btn-sm">
<span class="badge badge-dot mr-4">
<i class="bg-success"></i>Completed</button>
</form>
{% else %}
<button type="button" class="btn btn-default btn-sm">
<span class="badge badge-dot mr-4">
<i class="bg-warning"></i>Running</button>
{% endif %}
views.py:
def process(request):
hash_id = request.session.get('hash_id')
print(hash_id)
check = request.session.pop('check_status',)
if hash_id and check:
stat = status_mod.objects.filter(hash_id = hash_id).order_by('-id').first()
if stat:
stat = stat.stat_id
print(stat)
return render(request, 'enroll/status.html', {'status': stat})
urls.py:
path('status', views.process, name='process')
models.py:
class status_mod(models.Model):
id = models.BigIntegerField(primary_key=True)
stat_id = models.BigIntegerField()
class Meta:
db_table = "demo"
jquery / ajax in my status.html page:
<script>
$(document).ready(function() {
setInterval(function() {
$.ajax({
type: 'GET',
url: "{% url 'process' %}",
success: function(response){
console.log(response)
},
error: function(response){
alert("NO DATA FOUND")
}
});
}, 2500);
});
</script>
Now, I want to update my table row as situation will be if status == 1 then completed button will display else running. Hence it is working fine without ajax but I have to refresh again and again when process function is executed. So, I want to use ajax in this case to update the table row automatically without reloading it.

Why I can't fetch the json response of django using javascript fetch API?

I am new to JavaScript. I'm working on a project in which I'm using Django in the backend. My Django views function will produce a JSON response which my javascript fetch will get it. Here is my Django views function that produces a JSON response. My motive is to make a like button that will update the like button's appearance and the number of likes by clicking on that button without reloading the whole page. This is the last requirement of my project. I am trying for a long time, a couple of days.
def likepost(request,posts_id):
posts = NewPost.objects.get(id = posts_id)
is_like = False
for like in posts.likepost.all():
if like == request.user and request.method == "POST":
is_like = True
break
if not is_like:
posts.likepost.add(request.user)
else:
posts.likepost.remove(request.user)
posts.save()
# serialize_obj = serializers.serialize("json",posts_id)
return JsonResponse({
"is_like" : is_like,
"num_like" : posts.likepost.count()
},safe=False)
My javascript will make an API of the JSON data generated the above views function using fetch. Here is my javascript full code.
document.addEventListener("DOMContentLoaded",function(e){
// const colon = document.createElement('div');
// colon.setAttribute('id','colon')
e.preventDefault()
// const likebtn = document.createElement('button');
// likebtn.setAttribute('class','likebtn btn btn-primary');
// likebtn.setAttribute('class','likebtn');
// document.querySelector('.card-footer').appendChild(likebtn);
// document.querySelector('.likebtn').innerHTML = "Like";
document.querySelector(`#likebtn${posts_id}`).onsubmit = like_function();
// document.querySelector('.likepost').addEventListener('click', ()=> like_function('likepost'));
})
// let is_like = "{{is_like}}";
// let num_like = "{{num_like}}";
function like_function(){
// document.createElement('button').innerHTML = "Love";
fetch(`/like/${posts_id}`)
// ,{
// method:"POST",
// body : JSON.stringify({
// "is_like" : is_like,
// "num_like" : num_like,
// })
// })
.then(response => response.json())
.then(result => {
if(result.is_like){
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Unike";
// location.replace("http://127.0.0.1:8000")
}
else{
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Like";
// location.replace("http://127.0.0.1:8000")
}
})
}
// function like_function(){
// if (document.querySelector("#like").style.color == "blue"){
// document.querySelector("#like").style.color = "red";
// }else{
// document.querySelector("#like").style.color = "blue";
// }
// }
Here is my urls.py file.
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("profile/<int:id>",views.profilepage,name="profile"),
path("profile/<int:id>/following/addfollower",views.followersPeople,name="addfollower"),
path("profile/<int:id>/following/removefollower",views.followersRemove,name="removefollower),
path("postform", views.createpost, name="postform"),
path("editform/<int:id>",views.editpost,name="editpost"),
path("following",views.followerspost,name="following"),
path("like/<int:posts_id>",views.likepost, name="likepost"),
path("postpage/<int:id>",views.view_post,name="postpage"),
]+ static(settings.MEDIA_URL, document_root= settings.MEDIA_ROOT)
I am also sharing my template here.
{% load static %}
<div class="card-footer">
<form action="{% url 'likepost' posts_id=posts.id %}" class="likeform" method="POST" style="display: inline;">
{% csrf_token %}
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Like</button>
</form>
<small class="num_of_likes">{{ posts.likepost.all.count }}</small>
{% block script %}
<script>
let posts_id = "{{ posts.id }}";
</script>
<script src="{% static 'network/controller.js' %}"></script>
{% endblock %}
<button class="btn btn-link" style="text-decoration: none;">Comment</button>
View Post
{% if request.user.id is posts.user.id %}
Edit
{% endif %}
<div class="likepost"></div>
</div>
My project doesn't work well. When I click on the like button it appears like this
instead of updating the like button into the unlike button and the number of likes as well as the page shouldn't be reloaded. What should I do? Please let me know if I need to share more pieces of code although I see my code is very much messier.
In your video it looks like the form is being sent instead of preventing the POST default.
document.querySelector(`.likeform`).onsubmit = () => like_function();
Look into this answer for more detail about .onsubmit

REST API ajax not working

I am working on a school project where I have to program a REST API application that interacts with a database with basic POST and DELETE operation:
Here is my Python Flask file:
from flask import Flask, render_template, redirect, url_for, jsonify, request, Response, abort
from flask_bootstrap import Bootstrap
import dbinteraction
app = Flask(__name__)
Bootstrap(app)
#app.route('/')
def hello_world():
return redirect(url_for('index'))
#app.route('/index')
def index():
return render_template('index.html')
#app.route('/allrecipes')
def allrecipes():
return render_template('allrecipes.html')
#app.route('/ingredients')
def ingredients():
return render_template('ingredients.html')
#app.route('/api/v1.0/recipes', methods=['GET'])
def get_recipes():
# init
recipes = []
# get the task list from the db
recipes_list = dbinteraction.getRecipes()
# prepare the task list for jsonify
for item in recipes_list:
recipe = prepare_for_json(item)
recipes.append(recipe)
# return the task data
return jsonify({'recipes': recipes})
#app.route('/api/v1.0/ingredients', methods=['GET'])
def get_ingredients():
# init
ingredients = []
# get the user_ingredients list from the db
ingredients_list = dbinteraction.getIngredients()
# prepare the user_ingredients list for jsonify
for item in ingredients_list:
ingredient = prepare_for_json_ingredient(item)
ingredients.append(ingredient)
# return the ingredients data
return jsonify({'ingredients': ingredients})
#app.route('/api/v1.0/ingredients', methods=['POST'])
def insert_ingredient():
# get the request body
add_request = request.json
# check whether an ingredient is present or not
if (add_request is not None) and ('name' in add_request) and ('quantity' in add_request):
text = add_request['name']
quantity = add_request['quantity']
# insert in the database
dbinteraction.insertIngredients(text, quantity)
return Response(status=201)
# return an error in case of problems
abort(403)
#app.route('/api/v1.0/ingredients/<string:ing_name>', methods=['DELETE'])
def delete_ingredient(ing_name):
# delete the ingredient
ingredient = dbinteraction.removeIngredient(str(ing_name))
return Response(status=200)
def prepare_for_json(item):
"""
Convert the recipe in a dictionary for easing the JSON creation
"""
recipe = dict()
recipe['name'] = item[0]
recipe['link'] = item[1]
recipe['difficulty'] = item[2]
return recipe
def prepare_for_json_ingredient(item):
"""
Convert the ingredient in a dictionary for easing the JSON creation
"""
ingredient = dict()
ingredient['name'] = item[0]
ingredient['quantity'] = item[1]
return ingredient
if __name__ == '__main__':
app.run(debug=True)
I also programmed and tested the dbinteraction functions for the database and they work fine. My problem is in the ingredients.html part. I load and see the page as I want, a modifiable list of ingredients with the delete button. But when I click on the delete I get a Uncaught ReferenceError: (name of the ingredient) is not defined at HTMLAnchorElement.onclick
This are my html and javascript files:
{% extends "bootstrap/base.html" %}
{% block title %}All recipes page{% endblock %}
{% block styles %}
{{super()}}
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.12/css/all.css"
integrity="sha384-G0fIWCsCzJIMAVNQPfjH08cyYaUtMwjJwqiRKxxE/rx96Uroj1BtIQ6MLJuheaO9" crossorigin="anonymous">
{% endblock %}
{% block scripts %}
{{ super() }}
<script src="{{ url_for('static', filename='kima2js.js') }}"></script>
{% endblock %}
{% block content %}
<div class="container" style="text-align: center">
<h1><i class="fas fa-utensils" style=""></i><br>
Insert an ingredient:
</h1>
<div id="ingredients_list" class="form-inline"></div>
<div id="insertingredient">
<form id="addForm"class="form-inline" method="POST">
<div class="form-group">
<label for="ingredientName">Ingredient:</label>
<input type="text" id="ingredientName" class="form-control" name="name"/>
</div>
<div class="form-group">
<label for="ingredientQuantity">Quantity:</label>
<input type="text" id="ingredientQuantity" class="form-control" name="quantity"/>
</div>
<button type="submit" class="btn-sm">Add</button>
</form>
</div>
</div>
{% endblock %}
... the javascript:
function addIngredient() {
$("#ingredients_list ul").empty();
$("#ingredientName").val('');
$("#ingredientQuantity").val('');
getIngredients();
}
function getIngredients() {
$.getJSON("http://127.0.0.1:5000/api/v1.0/ingredients", function(data){
var ingredients = data["ingredients"];
var len = ingredients.length;
for(var i = 0 ; i<len ; i++) {
var t = ingredients[i];
$("#ingredients_list ul").append("<li class='list-group-item list-group-item-text'>"+t.name+" "+t.quantity
+" <a class='delete btn btn-default' onclick='deleteIngredient("+ t.name +")'>" +
" <span class='glyphicon glyphicon glyphicon-remove'></span>Delete</a></li>");
}
});
}
function deleteIngredient(ing_name) {
$.ajax("/api/v1.0/ingredients/"+ing_name,
{
method: 'DELETE',
success: function (status) {
// update the list of printed ingredients: called when the DELETE is complete
getIngredients();
}
}
);
}
$(document).ready(function () {
$("#ingredients_list").append("<ul></ul>");
$("#ingredients_list ul").empty();
getIngredients();
$("#addForm").submit( function(){
var name = $("#ingredientName").val();
var quantity = $("#ingredientQuantity").val();
var ingredient = {'name': name, 'quantity': quantity};
var json = JSON.stringify(ingredient);
$.post({
"url": "http://127.0.0.1:5000/api/v1.0/ingredients",
"data": json,
"contentType":"application/json",
"success": addIngredient
});
return false;
});
});
I can't see what I am doing wrong. My only guesses are on the onclick part. Because I have tested singularly all the other pieces of code in previous labs
You just need to make sure that the value of ing_name is in quotes when you write it as a parameter to onclick, as follows:
$("#ingredients_list ul").append("<li class='list-group-item list-group-item-text'>"+t.name+" "+t.quantity
+" <a class='delete btn btn-default' onclick='deleteIngredient(\""+ t.name +"\")'>" +
" <span class='glyphicon glyphicon glyphicon-remove'></span>Delete</a></li>");
Otherwise javascript thinks ing_name is a variable name (and the variable is not defined).

How to refresh a part of the DOM HTML when querying a foreign django view

Hello Awesome People!
So many questions on StackOverflow are about "How to refresh dom via jquery (from the same view/url)" It's not what I'm looking for.
With a website that large of its parts are running with ajax, I wonder how to refresh a part of the HTML DOM when querying a foreign django view.
Let me be clearer with some examples:
I have that view that sends all_users to template
def usersList(request):
all_users = User.objects.all()
return render(request,'administration/users-list.html',{'all_users':all_users})
In the template I loop through all_users... The 2nd <span> reflects the activation state of the user
{% for u in all_users %}
<span>{{forloop.counter}}.- {{u.name}} <span>
<span id='user_{{u.id}}_state'>
<button data-id='{{u.id}}' type='button' class='css-btn btn-circle'>
{% if u.is_activate %} Active{% else %}Inactive{% endif %}
</button>
<span>
{% endfor %}
With jquery, I send a request to a specific view responsible only to activate or deactivate the account of the user. We can activate/deactivate user in many parts of the website, that's why I do so in a different view.
Here's the view:
def deactivateUser(request):
user = request.user
if user.has_perm('is_admin') and request.is_ajax() and request.method == 'POST':
id_user = request.POST.get('id')
targeted_user = get_object_or_deny(User,id=id_user)
# get_object_or_deny is my own function
it will get the object or raise PermissionDenied otherwise
if targeted_user.is_activate:
targeted_user.is_activate = False
state = 'deactivated'
else:
targeted_user.is_activate = True
state = 'activated'
targeted_user.date_update_activation = NOW() # own function
targeted_user.save()
return JsonResponse({'done':True,'msg':'User successfully %s' %s state})
# Here we return a JsonResponse
raise PermissionDenied
So now, how can I refresh the Dom with following jquery stuff to get the current state of each user
$(document).on('click','.btn-circle',function(){
var id = $(this).data("id");
$.ajax({
url:'/u/de-activate/?ref={{ request.path }}',
type:'post',
data:{
csrfmiddlewaretoken:"{{ csrf_token }}",
id:id,
},
success:function(response){
$("#user_"+id+"_state").replaceWith($("#user_"+id+"_state",response));
if(response.created) alert(response.msg);
},
error:function(){
alert("An error has occured, try again later");
}
});
});
Note that all_users is required to loop through. deactivateUser() return a Json response, even though it doesn't returned it, it will not matter.
You can send http response, not json.
First, just move your html that want to change. in this situation,
{% for u in all_users %}
<div id="user-part">
<span>{{forloop.counter}}.- {{u.name}} <span>
<span id='user_{{u.id}}_state'>
<button data-id='{{u.id}}' type='button' class='css-btn btn-circle'>
{% if u.is_activate %} Active{% else %}Inactive{% endif %}
</button>
<span>
</div>
{% endfor %}
Then save it i.e. user_part.html
Second, make your view return HttpResponse with that html, and context. You can use either HttpResponse or render_to_response. I recommend render_to_response.
context = {
'all_users': all_users,
}
return render_to_response(
'path_to/user_part.html',
context=context,
)
Third, you just change script for replacing your html.
success: function(response){
$('#user-part').html(response);
prevent();
}

Django - Dictionary of Forms

I'm trying to implement a dictionary of forms where two fills are initialized with some values I have. I'm passing this through a Jquery function but when its going to add it to the template, the jquery function has an error that says Cannot set property 'value' of null when trying to execute this document.getElementById('example1').value = example;
My code here:
view.py
def exampleCaesar(request):
if request.is_ajax() and request.method == "GET":
form = caesarCipher(request.GET or None)
if form.is_valid:
wordToEncrypt = request.GET.get('word')
wordToEncrypt = wordToEncrypt.upper()
wordLength = len(request.GET.get('word'))
key = request.GET.get('the_key')
print(wordLength)
print(key)
equations = {}
for x in range(wordLength):
exampleForm = caesarCipher(initial={'letterOfWord' : wordToEncrypt[x], 'key' : key})
##print(exampleForm)
if exampleForm.is_valid:
equations = (exampleForm)
print(equations)
context = { 'equations' : equations
}
return render(request, "content/exampleCaesar.html", context)
Javascript file
$("#encryptButton").on({
click : function() {
var variable = document.getElementById('id_plaintext');
console.log(variable.value)
$.ajax( {
url: "/exampleCaesar",
type : "GET",
data: { CSRF: 'csrf_token',
word: $('#id_plaintext').val(),
the_key: $('#id_key').val()
},
success : function(example) {
$('#example1').show();
$('#example1').html(example);
document.getElementById('example1').value = example;
console.log(example);
}
}); //END OF Ajax
} //END OF FUNCTION
}); //END OF encryptButton
Template file
{% for letterOfWord, key in equations.items %}
<form onsubmit="return false;" method="GET" class="exaSubmit" enctype="multipart/form-data">
{% csrf_token %}
<div id="example1" type="hidden">
( {{ letterOfWord }} + {{ keyToUse }} ) MOD 26 =
{{ letterToFill }} <button name="action" class="validateButton" value="validate"> Validate </button> <br>
</div>
</form>
{% endfor %}
I believe I'm not filling the dictionary the right way. When I try to print it out in the console to see the values, only the names of the fields are but not the values. My bets are in this section but not entirely sure how's that possible when I'm appending the information to it.

Categories

Resources