Passing different URL parameters to AJAX function in Django - javascript

How to pass the different URL names to the javascript function. Here are my HTML and Javascript code.
{% for profile, g_name in group_list %}
<li class="contact">
<div class="wrap">
<img src="{{profile}}" alt="No image" />
<div class="meta">
<input type="hidden" id="myGroup" name="myGroup" value="{{g_name}}">
<button onclick="GetMessages()">
<p class="name">{{g_name}}</p>
</button>
</div>
</div>
</li>
{% endfor %}
<script>
function GetMessages() {
var myGroup = document.getElementById('myGroup').value;
$('.ajaxProgress').show();
$.ajax({
type: "GET",
url: "/getmsgs/"+myGroup,
success: function(response){
$("#display").empty();
...
},
error: function(response){
alert("No Data Found");
}
});
}
</script>
and this is my URL
path('getmsgs/<str:word>/', views.groupmsgs_ajax, name='groupmsgs_ajax'),
when I try the above method I am getting the first 'myGroup' id value. it is passing the first group name by default.
I am not able to call other group names.
Thank you for any help

That is because all input elements have the same id myGroup so document.getElementById('myGroup').value get always the first element value.
The following code changes should solve the issue given that g_id exists and is a string
{% for profile, g_name, g_id in group_list %}
<li class="contact">
<div class="wrap">
<img src="{{profile}}" alt="No image" />
<div class="meta">
<input type="hidden" id="{{g_id}}" name="{{g_id}}" value="{{g_name}}">
<button onclick="GetMessages({{g_id}})">
<p class="name">{{g_name}}</p>
</button>
</div>
</div>
</li>
{% endfor %}
<script>
function GetMessages(id) {
var myGroup = document.getElementById(id).value;
$('.ajaxProgress').show();
$.ajax({
type: "GET",
url: "/getmsgs/"+myGroup,
success: function(response){
$("#display").empty();
...
},
error: function(response){
alert("No Data Found");
}
});
}
</script>
Or pass the name directly to GetMessages function
{% for profile, g_name, g_id in group_list %}
<li class="contact">
<div class="wrap">
<img src="{{profile}}" alt="No image" />
<div class="meta">
<button onclick="GetMessages({{g_name}})">
<p class="name">{{g_name}}</p>
</button>
</div>
</div>
</li>
{% endfor %}
<script>
function GetMessages(myGroup) {
$('.ajaxProgress').show();
$.ajax({
type: "GET",
url: "/getmsgs/"+myGroup,
success: function(response){
$("#display").empty();
...
},
error: function(response){
alert("No Data Found");
}
});
}
</script>

Related

Understanding Ajax and adding cart count

website: https://www.fermento24.com
If you add a product to the cart, it'll show you the recently added product, total and possibility to go to cart. What I wanted to add was a count of the sort, like: There are currently another 5 products in the cart.
I tried to use {{ cart.item_count }}, but since the popup works on Ajax it doesn't seem to update on time, only showing me at the first time how many products were in the cart (thus, incorrect informations).
How do I go and implement something like this? What follows under is a test I did based on other answers I found here, but that still didn't work.
<div class="loading-modal modal">{{ 'general.search.loading' | t }}</div>
<div class="newsletter-success-modal">
<div class="modal-overlay"></div>
<div class="ajax-modal-content">
<a class="close close-window btn" title="{{ 'general.password_page.close' | t }}">
<i class="fa fa-times"></i>
</a>
<i class="fa fa-check" aria-hidden="true"></i>
<span>{{ 'general.newsletter_form.mailing_list_success_message' | t }}</span>
</div>
</div>
<div class="ajax-error-modal modal">
<div class="modal-inner">
<div class="ajax-error-title">{{ 'general.search.error' | t }}</div>
<div class="ajax-error-message"></div>
</div>
</div>
<div class="ajax-success-modal modal">
<div class="overlay"></div>
<div class="content">
<div class="ajax-left">
<p class="added-to-cart info">{{ 'cart.general.added_to_cart' | t }}</p>
<p class="added-to-wishlist info">{{ 'products.wishlist.added_to_wishlist' | t }}</p>
<img class="ajax-product-image" alt="modal window" src="/" />
<div class="ajax-cart-desc">
<h3 class="ajax-product-title"></h3>
<span class="ajax_price"></span>
<p>{{ 'cart.general.qty' | t }}: <span class="ajax_qty"></span></p>
</div>
</div>
<div class="ajax-right">
<div>Totale nel carrello: <span class="ajax_cartTotal"></span><br>
<span class="cart-item-count"> </span>
</div>
<button class="btn continue-shopping" onclick="javascript:void(0)">{{ 'cart.general.continue_shopping' | t }}</button>
<div class="success-message added-to-cart"><i class="fa fa-shopping-cart"></i>{{ 'cart.general.view_cart' | t }} </div>
</div>
<i class="fa fa-times-circle"></i>
</div>
</div>
<script type="text/javascript">
$(function(){
var cartCount = {{ cart.item_count }};
$('.varients-item').on('click', function(){
var obj = $(this);
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: {
quantity: 1,
id: $(this).attr("data-variant")
},
dataType: 'json',
success: function (data) {
$.ajax({
type: 'GET',
dataType: 'json',
url: '/cart.json',
success: function(cart){
cartCount++;
$('.cart-item-count').html(cartCount);
}
});
}
});
});
});
</script>
You need to update the code and your JS code is looks like similar to demo code below:
$(function(){
$('.varients-item').on('click', function(){
var obj = $(this);
$.ajax({
type: 'POST',
url: '/cart/add.js',
data: {
quantity: 1,
id: $(this).attr("data-variant")
},
dataType: 'json',
success: function (data) {
$.ajax({
type: 'GET',
dataType: 'json',
url: '/cart.js',
success: function(cart){
// once you get the data from AJAX API you need to get the latest count
let total = cart.item_count;
$('.cart-item-count').html(total);
}
});
}
});
});
});
Here is the reference for the cart.js over Shopify documentation.
Link

How to loop over an html with javascript?

I have an HTML code which looks like this:-
<article class="media content-section">
<div class="media-body">
<h2><a class="article-title" href="{% url 'post-detail' post.slug %}">{{ post.title }}</a></h2>
<div class="article-metadata">
<a class="mr-2" href="{% url 'blog-profile' name=post.author %}">{{ post.author }}</a>
<div class="float-right">
<small class="text-muted">Category</small>
<small class="text-muted">{{ post.date_posted }}</small>
</div>
<div style="float:right;">
<img style="height:19px; width:18px;" src="{% static "blog/viewicon.png" %}">
<p style="float: right; display: inline !important;" id="ViewCount">
.....
</p>
</img>
</div>
</div>
<p class="article-content">{{ post.content|truncatechars:200|safe }}</p>
</div>
</article>
I am trying to add the values of viewcount asynchronously to all the blogs field. With this js/ajax code:-
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous"></script>
<script>
$(document).ready(function(){
setInterval(function()
{
$.ajax({
type:'GET',
url: "{% url 'getBlogs' %}",
success: function(response){
$("#ViewCount").empty();
for (var key in response.blogs)
{
console.log(response.blogs);
var temp = response.blogs[key].view_count
$("#ViewCount").append(temp);
}
},
error:function(response){
alert("No Data Found");
}
});
},1000);
});
</script>
I have many such blogs, But the values seem to be displayed all at once at only a single field which looks like this:-
But I am trying to display the viewcount of each blogs to its dedicated position. Is there I anyway I can achive it.
One of the easiest way is to use HTML markup to differentiate different viewCount using data attributes.
blogs={
"1":{
"view_count":1
},
"2": {
"view_count":15
}
}
for (var key in blogs)
{
var temp = blogs[key].view_count
$(`[data-key=${key}]`).append(`${temp} views`);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p data-key="1" id="ViewCount">Key:1 :- </p>
<p data-key="2" id="ViewCount">Key:2 :- </p>

How to identify multiple forms in one template?

I'm trying to implement a follower/following system in Django. In the template, all follow requests have a user and they all have user id's that can be displayed. The template is a profile page that contains several follow requests made by other users. I have created a separate form for each accept/decline and I want to uniquely identify each form so that I can submit that one and remove it subsequently.
<div class="col s12 l6 trending-panel container">
<h4>
Requests
</h4>
<div class="divider"></div>
{% for bond_request in bond_requests %}
{% if bond_request.accepted == False %}
<div>
<div class="row bond-request-row" id="{{bond_request.by_user.id}}">
<div class="col s6">
<a href="{% url 'accounts:profile' bond_request.by_user.username %}">
<div class="col s8">
<img class="profile-image-request" src="https://m.media-amazon.com/images/M/MV5BNjUxNDcwMTg4Ml5BMl5BanBnXkFtZTcwMjU4NDYyOA##._V1_.jpg" alt="">
</div>
<div class="col s4">
<h6 id="follower-username">
#{{bond_request.by_user}}
</h6>
</div>
</a>
</div>
<div class=" col s12 center accept-decline-margin">
<div class="col s12 l6">
<form action="accounts:accept_bond_request" method="POST" id="bond-request-accept-form">
<!-- <a href="#" id="bond-request-accept" class="green-text white btn">
<div>
<ion-icon name="add"></ion-icon>
<span>Accept</span>
</div>
</a> -->
<button id="bond-request-accept" class="green-text white btn" type="submit">Accept</button>
</form>
</div>
<div class="col s12 l6">
<a href="" class="grey-text white btn">
<div class="">
<ion-icon name="remove"></ion-icon>
<span>Ignore</span>
</div>
</a>
</div>
</div>
</div>
<!-- HERE -->
</div>
{% else %}
{% endif %}
<div class="divider">
</div>
{% endfor %}
</div>
$("#bond-request-accept-form").on('submit',function(){
// Cleans the username
// var each_bond_request = $();
var raw_follower_username = $("#follower-username").text().trim();
var follower_username = raw_follower_username.replace("#","");
console.log("Follower username: ",follower_username);
$.ajax({
type: "POST",
url: "/accounts/user/" + follower_username + "/accept_request",
data:{
"follower_username" : follower_username,
},
success: function(data){
console.log(data);
M.toast({html: follower_username + ' started following you',classes: 'green'}, );
},
error: function(data){
console.log("All error data: ",data);
M.toast({html: 'Failure',classes: 'red'}, );
},
});
});
You should create a standalone function to handle submit. And reference this function in each form you created.
function SubmitHandler (e) {
// Cleans the username
// var each_bond_request = $();
var raw_follower_username = $(e).find("#follower-username").text().trim();
var follower_username = raw_follower_username.replace("#","");
console.log("Follower username: ",follower_username);
$.ajax({
type: "POST",
url: "/accounts/user/" + follower_username + "/accept_request",
data:{
"follower_username" : follower_username,
},
success: function(data){
console.log(data);
M.toast({html: follower_username + ' started following you',classes: 'green'}, );
},
error: function(data){
console.log("All error data: ",data);
M.toast({html: 'Failure',classes: 'red'}, );
},
});
return false;
}
Then in your template:
...
<form id="bond-request-accept-form" onsubmit="SubmitHandler(this)">
...
Note the #follower-username should be nested within the form tag for jQuery to find the correct one.
First, I just want to say that I may be understanding your question wrong. If so, feel free to correct me.
If I am understanding this right, you have multiple copies of essentially the same form with slight variations depending on the user that is sending the request. Since IDs are meant to be unique and can cause issues in JavaScript if there are more than one instance of them, I would change the bond-request-accept-form to a class rather than an ID, and do something like this in JQuery:
$(".bond-request-accept-form").toArray().forEach(function(elem){
$(elem).on('submit', function(){
// Logic to perform when the form is submitted
});
});
Put different URLs in the action for the two forms. Then you'll have two different view functions to deal with the two different forms.

Django - csrf token not defined

What this code is supposed to do is let a user click they're description and be able to edit it. I have the modal popping up, but the save button will not save the data and produces the following error:
Uncaught ReferenceError: csrftoken is not defined
at HTMLButtonElement.<anonymous> (modalShortListDescription.js:6)
at HTMLButtonElement.dispatch (jquery.min.js:3)
at HTMLButtonElement.r.handle (jquery.min.js:3)
Here's where the modal is called:
<div class="tab-content col-xs-12">
{% for list in lists %}
<input type="hidden" id="idList" id_list="{{list.id}}">
{% if forloop.first and not createTabActive %}
<div role="tabpanel" class="tab-pane fade active in" id="list{{list.id}}">
{% else %}
<div role="tabpanel" class="tab-pane fade" id="list{{list.id}}">
{% endif %}
<div class="content col-xs-12">
<div class="form-horizontal sort-by col-xs-12">
<h3>Description</h3>
{% if list.description %}
{{list.description}}
{% else %}
None
{% endif %}
{% include "layout/popUp/modal-short-list-description.html" %}
</div>
Here's the modal itself:
<div class="modal fade" id="modalDescription{{list.id}}" role="dialog">
<div class="modal-dialog">
<form class="form-horizontal" action="{% url 'update-list-description' %}" method="post">
{% csrf_token %}
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Description</h4>
</div>
<div class="modal-body modal-body-exper modal-body-value modal-body-t">
<div class="lineEnterValue lineTeamSize lineTitle">
<div class="form-group {% if form.description.errors %} has-error{% elif form.is_bound %} has-success{% endif %}">
<div class="col-sm-10">
<textarea name="{{ form.description.html_name }}" class="form-control" id="{{ form.description.id_for_label }}" rows="5" style="margin: 0px; height: 90px; width: 455px;"></textarea>
</div>
{% if form.description.errors %}
<ul class="col-sm-10 col-sm-offset-2 error-list text-danger">
{% for error in form.description.errors %}
<li>{{ error|escape }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
</div>
<div class="modal-footer modal-footer-value">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary" id="description_save">Save</button>
</div>
</div>
</form>
</div>
Here is the .js that the save button uses:
$(document).ready(function() {
$("#description_save").click(function() {
var description = $("#form.description").val();
var idList = $("#idList").attr("id_list");
var url = "/bid/update-list-description";
csrftoken();
$.ajax({
type: "POST",
url: url,
data: {description : description, idList: idList},
}).done(function(response){
$(".modalDescription").modal("hide");
$(".editDescription").text(description);
});
})
})
EDIT:
views.py:
#csrf_protect
def updateListDescription(request):
checkEmployer(request)
pageClass="my-short-lists search-for-prospect"
#shortList = get_object_or_404(List, id = request.POST.get("idList"))
shortList = request.user.profile.profile_employers.employer_lists.filter(pk=request.POST.get("idList"))
if request.method =="POST":
form = ListForm(request.POST)
if form.is_valid():
shortList.description = form.cleaned_data["description"]
shortList.save()
else:
form = ListForm()
return redirect('my-short-lists')
EDIT:
I think the problem lies in not only csrftoken, but also in the button: if a button calls ajax, it should not be submit. If it posts the form, it should not do ajax call. It seems that you add the token in the form, but ajax does his thing first... So the first answer seems valid.
Or,
You can instead add a header to every ajax call in $.ajaxSetup(). The DOC has this part explained:
Define the getCookie(name) method;
Define var csrftoken = getCookie('csrftoken');;
Use these lines:
That is:
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
Then you don't have to change any ajax call. The header is attached in every ajax call.
https://docs.djangoproject.com/en/2.0/ref/csrf/, under "Ajax" section.
I have used this approach and it worked.
The AJAX POST doesn't include the csrf_token. Add:
'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
into $.ajax data (along with description and idList) and remove csrftoken().
Edit your js to this
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
$(document).ready(function() {
$("#description_save").click(function() {
var description = $("#form.description").val();
var idList = $("#idList").attr("id_list");
var url = "/bid/update-list-description";
var csrftoken = getCookie('csrftoken');
$.ajax({
type: "POST",
url: url,
data: {description : description,
idList: idList,
csrfmiddlewaretoken: csrf_token
},
}).done(function(response){
$(".modalDescription").modal("hide");
$(".editDescription").text(description);
});
})
})

Using ajax and django to delete an item in for loop

Trying to delete a post/comment by using the bootstrap × on click and fade out. I have some code written up but it isn't working. I feel I am missing something so simple. Any guidance or help would be highly appreciated.
urls.py
url(r'^delete/(?P<pk>\d+)/$', views.delete, name='delete'),
views.py
#login_required
def delete(request, pk):
warn = get_object_or_404(Warning, pk=pk)
fop = get_object_or_404(Followers, pk=warn.person.pk)
warn.delete()
return redirect('yardsale.views.follower_warnings', pk=fop.pk)
template
{% for warns in warn.warnings.all %}
<div class="warning-list col-md-4">
{# <a href="{% url 'delete' pk=warns.pk %}"> #}
<button type="button" class="close">×</button>
{# </a> #}
<div class="publish-date"><strong>Warned:</strong> {{ warns.publish_date }}</div>
<div class="posted-by"><strong>Warned By: </strong> {{ warns.author }}</div>
<div class="warningtype"><strong>Warning Type: </strong>{{ warns.WarningType }}</div>
<div class="description">
<strong>Description:</strong> {{ warns.descript }}
</div>
{% endfor %}
main.js
$(".close").click(function () {
if (confirm("Are you sure you want to delete this?")){
$.ajax({
type: "DELETE",
url: "{% url 'delete' pk=warns.pk %}",
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
}
success: function() {
var close=$(this).parent();
close.fadeOut(1000);
});
}
})
}
});
The main.js is as follows.
$(".close").click(function () {
var close=$(this).parent();
if (confirm("Are you sure you want to delete this?")){
$.ajax({
type: "DELETE",
url: $(this).data('url'),
beforeSend: function(xhr) {
xhr.setRequestHeader("X-CSRFToken", getCookie("csrftoken"));
},
success: function() {
close.fadeOut(1000);
}
});
}
});

Categories

Resources