How to get specific id from for loop in django template? - django

I'm working with django and javascript, I'm trying to follow and unfollow multiple users without refreshing the page. therefore i'm using ajax. The problem which i'm facing right now is that the first follower is getting follow and unfollow no matter if i click on that user or on other user.. its an obvious behavior because i couldn't understand how to get specific id of user from the for loop so that i can use that user in a js function.
{% if follower.user in request.user.userprofile.follower.all %}
<span><a class="btn btn-success" id="follow-button{{follow.id}}" toggle="{{follower}}" type="submit">{% csrf_token %}UnFollow</a></span>
{% else %}
<span><a class="btn btn-warning" id="follow-button{{follow.id}}" toggle="{{follower}}" type="submit">{% csrf_token %}Follow</a></span>
{% endif %}
</div><!--/ followers-body -->
{% endfor %}
<script>
$(document).on('click','a[id^=follow-button]', function (e) {
var user = $('#follow-button').attr('toggle'); //this user is coming the first use of looping object..no matter if i click on the 2nd or 3rd user of the loop.
console.log(user,'im im im tested');
e.preventDefault();
$.ajax({
type: 'POST',
url: '{% url "profiles:toggle" %}',
data: {
user_toggle: user,
csrfmiddlewaretoken: $('input[name=csrfmiddlewaretoken]').val(),
action: 'POST',
},
success: function (json) {
result = json['result']
console.log(result,"maii mai maima maima a")
if (result) {
document.getElementById("is_following").innerHTML = '<a class="btn btn-success" id="follow-button" toggle="{{user.userprofile}}" type="submit">{% csrf_token %}UnFollow</a>'
}
else
document.getElementById("is_following").innerHTML = '<a class="btn btn-warning" id="follow-button" toggle="{{user.userprofile}}" type="submit">{% csrf_token %}Follow</a>'
},
error: function (xhr, errmsg, err) {
}
});
})
</script>

It is more of JS/JQuery question than a Django one, but here is what I think you are missing.
When you add a listener to an element, you have an option to get the element that was interacted with using the saved word this.
Your problem in the code is that line where you retrieve user. If you replace $('#follow-button') with $(this) then you will get the user that was clicked.
From there you can retrieve the id easily.

Related

Not able to retrieve variable in template in Django ajax call

I am trying retrieve counter value passed from view in the html template .It is coming as None, however in the view print and in ajax success log value it is coming correct.
JS ajax func
$(".pos").click(function(){
counter=counter+1;
$(".add").html('add counter '+counter);
$.ajax(
{ url :'page',
type :'get' ,
data:{
quantity: counter
},
success:function(response){
console.log(response);
}
}
);
My view
def page(request):
counter=request.GET.get('quantity')
print(counter) ## this is printing fine
return render(request,'page.html',{'counter':counter})
html template
<body>
{{counter}}
<button class="btn neg" name="neg-btn">-</button>
<button class="btn add" name="add-btn" >add to box</button>
<button class="btn pos" id="test" name="pos-btn">+</button>
</body>
getting this counter as None
Usually you would have two views, one to render the template and another for your ajax request. This helps to keep your code more organized and have functions do exactly one task as most of the its described in its naming.
One important thing that is happening in your view, is that you are returning the HTML generated by the render API and not the counter value. Of course, there are many ways to do this correctly, but here is one possible solution:
page.html
{% extends 'base.html'%}
{% block content %}
<body>
<div id="counter">
{{counter}}
</div>
<button class="btn neg" id="neg" name="neg-btn">-</button>
<button class="btn add" id="add" name="add-btn" >add to box</button>
<button class="btn pos" id="pos" name="pos-btn">+</button>
</body>
{% endblock content %}
{% block script %}
<script>
let counter = parseInt("{{counter}}");
let page_url = "{% url 'core:page' %}";
console.log(page_url)
$( "#pos" ).click(function() {
counter += 1;
$( "#counter" ).replaceWith(`<div id="counter">${counter}</div>`);
});
$( "#neg" ).click(function() {
counter -= 1;
$( "#counter" ).replaceWith(`<div id="counter">${counter}</div>`);
});
$( "#add" ).click(function() {
$.ajax({
url :page_url,
type :'post' ,
data:
{
counter: counter,
csrfmiddlewaretoken: '{{ csrf_token }}',
},
success:function(response){
console.log(response);
}
});
});
</script>
{% endblock script %}
views.py
from django.http import JsonResponse
def page(request):
counter = 0
if request.method == 'POST':
counter = int(request.POST.get('counter'))
print(counter)
return JsonResponse({'counter': counter})
return render(request,'page.html',{'counter':counter})

got problem in the ajax form submission code

<form action="" method="post" class="f-color" id="email-form">
{% csrf_token %}
<label>Name</label>
<input type="text">
<label>From</label>
<input type="email">
<label>Message</label>
<button type="submit">Sent</button>
</form>
<div class="mt-5" id="spin" style="display: none;">
<div class="loader"></div>
</div>
<div id="msg"></div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
$(document).on("submit", "#email-form", function(event){
event.preventDefault();
$('#spin').show();
$.ajax({
url: "{% url 'contact' %}",
type: "POST",
data: $("#email-form").serialize(),
success: function(data){
$("#spin").hide();
if(data.status == "success"){
$("#msg").html("<p class='alert alert-success'>we will get back to you as soon as possible</p>" );
$("#email-form").reset();
}
}
})
})
})
</script>
using this code I can submit the form successfully, but after the form submission the message(msg) not showing, the 'if condition statement' is perfectly working (for the testing I gave the alert, the alert was worked)
another problem is form reset, for this I'm using
$("#email-form").reset();
but the form dose't reset
how can I solve these problems
try
$('#email-form')[0].reset();
https://stackoverflow.com/a/3786702/8640027
I got a solution for the resetting form after the ajax form submission
$("#email-form").trigger("reset");

Django - POST method not working for those forms created within a FOR loop in template

I'm using a for loop in a template to create multiple forms with method="post" that work with Ajax. But only the form for the first element of items_list works fine, the rest do not work at all showing error 405 0 Method Not Allowed. I think they all should work the same way. And just wondering if this issue was caused by a for loop or something else.
cart_items.html:
<script>
$(document).ready(function () {
$("#remove").click(function (event) {
event.preventDefault();
$.ajax({
url: '{% url "cart:remove_from_cart" %}',
type: "POST",
dataType: 'json',
data: {bookID: $('#idInput').val()},
success: function (response_data) {
alert('works fine')
},
error: function (response_data) {
console.log('error occurred');
}
});
});
});
</script>
{% for book in items_list %}
<div class="items">
<p id="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
<form method="post">
{% csrf_token %}
<input id="idInput" value="{{ book.book.id }}" >
<button id="remove" type="submit"> Remove</button>
</form>
</div>
{% endfor %}
The code in the function body below is just for testing. Once the first form works, I guess the problem was not caused by the function view.
cart/views.py:
#csrf_exempt
def remove_books(request):
cart = Cart.objects.get(user=request.user)
if request.method == 'POST':
passed_id = request.POST['bookID']
secured_id = int(passed_id)
response_data = {
'quantity': secured_id
}
return JsonResponse(response_data)
<script>
$(document).ready(function () {
$(".remove").click(function (event) {
// event.preventDefault(); // don't think it should be required with button type=button
var book_id = $(this).parent().find('.idInput').val(); // find correct input box.
var csrf = $('input[name="csrfmiddlewaretoken"]').val(); // get csrf token in variable.
// there are multiple ways to get csrf token, I personally like this ^^, see https://docs.djangoproject.com/en/2.1/ref/csrf/#ajax for more
$.ajax({
url: '{% url "cart:remove_from_cart" %}',
type: "POST",
dataType: 'json',
data: {
bookID: book_id,
csrfmiddlewaretoken: csrf // add csrf token to post data
},
success: function (response_data) {
alert('works fine')
},
error: function (response_data) {
console.log('error occurred');
}
});
});
});
</script>
{% csrf_token %} <!-- It will render a hidden input field with csrf token in it. Keep it outside for loop but in html. No need to render exactly same element multiple times. -->
{% for book in items_list %}
<div class="items">
<p class="title"> {{ book.book.title }}, quantity: {{ book.quantity }} </p>
<form method="post">
<input class="idInput" value="{{ book.book.id }}" > <!-- use class not id -->
<button class="remove" type="button"> Remove</button> <!-- you can use button type=button to avoid form submit and hence avoid event.preventDefault(); in js -->
</form>
</div>
{% endfor %}

Accessing a widgets value in django template

I need to do an ajax call in django depending on the values set on two date fields and a select dropdown. In order to do that I have to pass those values into javascript function which will be called when a button is click. I have set the form dates fields as Date type and select as Choice field. How can I pass the current values of these to the javascript function?
form.html (template):
<div class="form-group">
<label class="control-label">* Start Date:</label><br>
{{ form.date1 }}
</div>
<div class="form-group">
<label class="control-label">* End Date:</label><br>
{{ form.date2 }}
</div><br><br>
<div class="form-group">
Category: {{ form.category }}
</div>
<button type="button" class="btn btn-xs btn-warning"
onclick="javascript:check_availability({{ XXX }}, '{% url "find_available" %}');">
Check Now
</button>
Javascript:
function check_availability(date1, date2, category, url) {
$.ajax({
type: 'GET',
url: url,
data: {date1: date1, date2: date2, category: category},
dataType: 'json',
success: available_now,
error: function() {
alert('Unable to find available items')
}
});
}
fucntion available_now () {...}
In form.py (view)
category = forms.ChoiceField(choices=(...))
date1 = forms.DateField(widget=forms.DateInput())
date2 = forms.DateField(widget=forms.DateInput())
How could I pass those three values set in the widgets in place of XXX for the above function call? I need to specifically get the selected value of the dropdown.
This isn't in any way a question about Django, but about Javascript. Since you are using jQuery for your Ajax function, you should use it to get the value of the fields. Also note, you should avoid setting onclick handlers directly in the HTML; you should do that in your jQuery script as well.
<button type="button" id='find-available' class="btn btn-xs btn-warning" data-url='{% url "find_available" %}');">
Check Now
</button>
...
$('form').on('click', '#find-available', function() {
$this = $(this);
$.ajax({
type: 'GET',
url: $this.data('url'),
data: $this.parent().serialize(),
dataType: 'json',
success: available_now,
error: function() {
alert('Unable to find available items')
}
});
});

Display Form Field based on other Fields within the Django Form

I am trying to create a way to only display certain fields within a django form based on the bound data of another field within that same form. I'm familiar with the idea of form.field.bound_type but I'm not sure how to continually check for state change on a field in a form and update the other field accordingly. Something like if you were filling out an application and it asked if you've committed a crime, if you click yes then a details text area pops up.
I'm using:
Django 1.8.4
Bootstrap3 6.6.2
As it pertains to this question. Here is what I've currently got with the field values edited for work protection. It does SORT of work. Meaning the form is fine, the if statement works initially but it doesn't reevaluate the if once the specified field has changed.
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
{% bootstrap_field form.field_three%}
{% if form.field_three.bound_data == "A Value" %}
{% bootstrap_field form.field_four%}
{% endif %}
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>
Solution:
With Birdie's help I was able to figure out the solution. For anyone who has hit this same Django related problem here is how you add or remove fields based on another field in the same form.
<script>
// function that hides/shows field_four based upon field_three value
function check_field_value(new_val) {
if(new_val != 'A value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#field_four').removeClass('hidden');
} else {
$('#field_four').addClass('hidden');
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#field_three').change( function() {
check_field_value(this.value);
});
});
</script>
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
<div id="field_three">{% bootstrap_field form.field_three%}</div>
<div id="field_four">{% bootstrap_field form.additional_notes %}</div>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>
You cannot do this within the template because the template is executed on the server side, but the user interaction occurs on the client side.. in the browser. This must be done in javascript and run in the browser.
Here is an example of jQuery code which does this. I did not test it so it may need tweaking, but this should get you in the right direction.
You will need to look at your HTML to determine the id of the element you actually want to hide() and show(). Normally you would have some kind of HTML element (eg. a DIV) surrounding both the field or fields you want to hide as well as the label(s).. and you would hide everything at once by hiding the element which contains all the fields, rather than each individual field itself.
If you add the HTML surrounding field_four to your question, I will update the answer to work with what you've got...
<script>
// Ideally this script (javascript code) would be in the HEAD of your page
// but if you put it at the bottom of the body (bottom of your template) that should be ok too.
// Also you need jQuery loaded but since you are using bootstrap that should
// be taken care of. If not, you will have to deal with that.
// function that hides/shows field_four based upon field_three value
function check_field_value() {
if($(this).val() == 'A Value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#id_field_four').hide();
} else {
$('#id_field_four').show();
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#id_field_three').change(check_field_value);
// set the state based on the initial values
check_field_value.call($('#id_field_three').get(0));
});
</script>
Thanks all for the contribution, but I could not get the code above work. This is my solution:
<script>
function hideField() {
check = document.getElementsByName("put your field name here")[0].value;
response = document.getElementById("put your id here");
if (check === "Open") {
response.style.display = "none";
}else{
response.style.display = "block";
}
}
</script>
The key is to figure out Id for the field you want to hide, and name for the field you check. I did NOT use DIV container to assign the id and the name, but inspected rendered HTML page with developer tools in the browser. Let me know if you have questions or want more detailed explanation.
I found this question very interesting. I have updated it with bootstrap 4.0v, with the following script, I hope it can help someone:
<script>
// function that hides/shows field_four based upon field_three value
function check_field_value(new_val) {
if(new_val != 'A value') {
// #id_field_four should be actually the id of the HTML element
// that surrounds everything you want to hide. Since you did
// not post your HTML I can't finish this part for you.
$('#field_four').removeClass('d-none');
} else {
$('#field_four').addClass('d-none');
}
}
// this is executed once when the page loads
$(document).ready(function() {
// set things up so my function will be called when field_three changes
$('#field_three').change( function() {
check_field_value(this.value);
});
});
</script>
<form action= "/send_email/" method="post" class='col-sm-5'>
{% csrf_token %}
{% bootstrap_field form.field_one%}
{% bootstrap_field form.field_two%}
<div id="field_three">{% bootstrap_field form.field_three%}</div>
<div id="field_four">{% bootstrap_field form.additional_notes %}</div>
{% buttons %}
<button type="submit" class="btn btn-primary">
{% bootstrap_icon "glyphicon glyphicon-ok-circle" %} Submit
</button>
{% endbuttons %}
</form>