Django & Ajax : data get lost between the view and the template - django

Using Ajax and Django, my data get lost when sent back to my template and I can't retrieve them.
Here is my code and the logic :
Following the dependent dropdown lists tutorial offered by ["Simple is Better Than Complex"][1]
I have implemented an Ajax request.
Here is the html code:
<p class="multiple-choice" id="mandate-city" data-url="{% url 'officials:ajax_load_mandate_city' %}">Local Mandate: {{ form.mandate_city }}</p>
The ajax request is fired from this script:
<script>
$("#id_departments").change(function (){
var url = $("#mandate-city").attr("data-url");
var departmentId = $(this).val();
$.ajax({
url: url,
data: {
'department': departmentId
},
success: function (data){
$("#id_mandate_city").html(data);
console.log(data);
}
});
});
</script>
After check with console.log, the data are collected by the script. Then, they reach the view.
Here is my view:
def load_mandate_city(request):
department_id = request.GET.get('department')
mandate_city = MandateCity.objects.filter(department_id=department_id).order_by("department")
return render(request, "officials/mandate_city_list.html", {mandate_city: mandate_city})
With a print, I have checked, and the data are treated as planned.
Then the data are sent back through the url:
path('ajax/load_mandate_city/', views.load_mandate_city, name="ajax_load_mandate_city")
They seem not to reach the template:
{% for mandate in mandate_city %}
<option value="{{ mandate.pk}}">{{ mandate.get_mandate_display }}</option>
{% endfor %}
And I could not track them in my script. :-/
Can somebody let me know where the bug is ?
Thanks.
[1]: https://simpleisbetterthancomplex.com/tutorial/2018/01/29/how-to-implement-dependent-or-chained-dropdown-list-with-django.html

did you try to return the information in a json object and then render it with client side js? in general when you use ajax (or fetch) you wanna use the information returned so it's better to return it as a data type,
if you do want to return the html response you should probably not use ajax but rather a form

Related

Accessing Objects Attributes Within Ajax

I am adding ajax to my website. I originally had this button:
{% for item in notifications %}
<a class='delete' href="{% url 'delete' item.slug %}">
But changed it to Ajax.
{% for item in notifications %}
<a class='delete'>
$(document).on('click', '.delete', function (e) {
$.ajax({
url: '/users/ajax/delete/',
data: {
// here I was to call the 'delete' function in the 'django.notifications' package
// something like 'notifications.delete(slug)'
},
dataType: 'json',
success: function (data) {
alert("Working");
}
});
});
This Ajax fires correctly, but I don't know how to get item.slug in Ajax. I guess I could do this <a class='delete' slug="{{ item.slug }}"> and access the slug, but it seems really sloppy.
Is there a way to pass an object's attributes to Ajax without setting it as a value within the html code itself?
Thank you.
You can store the value of the notification in a variable while rendering the HTML as shown below in the HTML section. Once you have notifications value in your script code. You can check the index of the clicked anchor and retrieve the item associated with that index.
$(document).on('click', '.delete', function(e) {
let elem = $(this);
$.ajax({
url: '/users/ajax/delete/',
data: {
// here I was to call the 'delete' function in the 'django.notifications' package
// something like 'notifications.delete(slug)'
},
dataType: 'json',
success: function(data) {
alert("Working");
//new code below
let index = $("a.delete").index(elem);
let item = notifications[index];
//You can access slug and other attributes of item now.
}
});
});
<script>
const notifications = {% notifications %}
</script>

How to get response back from Django API to Calling HTML Page i am posting an image to Api?

How I can call a Django API from another Django Project (or from any other project) and get the response back after some processing on the same calling page (the page from which I called the API)
I am calling the API from form action ....but API shows the response in a new blank page
Here is API CODE: (//skipping some code to avoid confusion)
def IdealWeight(request):
#defining a list of data to send back to html
list_of_data=[]
list_of_data.append(name)
list_of_data.append(fatherName)
list_of_data.append(registration)
print(list_of_data)
# outPut_Data = ast.literal_eval(list_of_data)
# return render(request,'LibraryForm.html',{'data1':outPut_Data})
return JsonResponse(list_of_data,safe=False)
I want list_of_data on the calling page in some variable.
Here is my HTML Code from which i am calling the API:
<form action="http://127.0.0.1:8000/idealweight/?image/" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<input type="file" class="form-control-file" name="image" onchange="readURL(this);" required>
<input type="submit" class=" btn btn-primary" title="Process" value="Process" id="processButton">
</div>
{{ data1 }}
</form>
From HTML page, I am sending a picture to API (API build in Django)
and from that, I want to send an array or list of data extracted from the image and want to show that on same HTML page....................from which I called the API how I can do that?
hope I am clear what I want?
Using an Ajax call would be better choice. you would be doing something along the line.
$(document).ready(function (e) {
$('#upload').on('click', function () {
var file_data = $('#file').prop('file');
var form_data = new FormData();
form_data.append('file', file_data);
$.ajax({
url: 'http://127.0.0.1:8000/idealweight/?image/',
contentType: false,
data: form_data,
type: 'post',
success: function (response) {
// use response to update html
},
error: function (response) {
// use response to update html
}
});
});
});
and your template would be something like
<input type="file" id="file" name="file"/>
<button id="upload" type="button">Process</button>
note: you might get cross origin request block error. so you have to allow that explicitly.

Django: how to add csrf token when prepending a from using ajax

I am adding a comment functionality in my project. And I am using ajax to make it dynamic so that when the user clicks on the comment submit button it will be added in the comment section dynamically without refreshing the page. But the problem is when prepending a form using ajax I cant add csrf token like this
{% csrf_token %}
in the form because ajax wouldn't understand it and take it as text.
function getids(postid){
console.log(postid)
$(postformid).one('submit', function(event){
event.preventDefault();
console.log(event)
console.log("form submitted!") // sanity check
create_comment(posted);
});
}
// AJAX for posting
function create_comment(postid) {
console.log("create comment is working!") // sanity check
console.log(postid)
console.log(talkid)
$.ajax({
url : "create_comment/"+postid, // the endpoint
type : "POST", // http method
data : { the_comment : $(cmtext).val() }, // data sent with the post request
// handle a successful response
success : function(json) {
$(cmtext).val(''); // remove the value from the input
console.log(json); // log the returned json to the console
$(talkid).prepend(
"<div class='col-1 p-0'><form' id=upvote' method='POST'>{%"csrf_token"%}<button
class='btn btn-md btn-outline-danger btn-
block p-auto' id='btnid' onclick='---' type='submit'></button></form></div>");
console.log("success"); // sanity check
},
// handle a non-successful response
error : function(xhr,errmsg,err) {
}
});
};
pretending my form here
<div class="row m-0" id="talk{{post.id}}"></div>
is there any other way around?
Use
{% csrf_token %}
just before the form tag inside your template.

How to get an element from list based on clicked link in Django Template?

I'm creating private messages application, and I render my messages this way:
return render(request,'mssg/mssg_page.html', {'inbox':inbox, 'current_mssg':current_mssg,})
Inbox contain all messages. Current message is a one that should be fully displayed. I made a list of messages that look like this in my template:
{% for mssg in inbox %}
<a href="#"><!-- here -->
<div class="right">
<h3>{{ mssg.mssg_from.username }} <small>{{ mssg.delivery_date }}</small></h3>
<h2>{{ mssg.title|safe }}</h2>
<p>{{ mssg.text|safe|truncatewords:15 }}</p>
</div>
</a>
{% endfor %}
I display full current message in same template too.
I wants to change current message after clicking on link with <!-- here --> commment
I know that I can send message id to view, validate it and send it back to template. But it needs page to be refreshed. However all messages are already in template listed in inbox so there should be no need to refresh page. I also know that it's possible to pick an message from inbox like this {{inbox.0}}
But I have no idea how to make it depended on clicked link. I guess that javascript is needed for it. But I even if I know that I can do something like inbox[0] by placing inbox.0 in template I still don't know how to do something like inbox[varriable].
Is there a way to do it?
I don't want my page to refresh if it don't have to do it.
PS I'm using bootsrap
Using AJAX will solve your problem. See this StackOverflow answer which explains how to do that:
$('a').click(function() { // This is a listener to the link you mentioned.
$.ajax({
url: '127.0.0.1:8000/your_ajax_url', // You will need to create a URL for your AJAX call.
type: 'get', // This is the default though, you don't actually need to always mention it
success: function(data) {
alert(data);
},
failure: function(data) {
alert('Got an error dude');
}
});
}

how to refresh in a div values from a model with jquery .ajax() to django

I have a view which returns a chained object of 3 models
def test(request):
output=itertools.chain(
model1.objects.all(),
model2.objects.all(),
model3.objects.all()
)
return render_to_response('test.html', {'output':output})
In the html, I added an anchor and a jQuery script, which should replace the #output with new values just from model1
<html>
<head>...</head>
<body>
<script>
$(document).ready(function() {
$("#switch").click(function() {
$.ajax({
url: $(this).attr("href"),
success: function(result) {
//whatever I put here is not triggered
}
});
});
});
</script>
<a id="switch" href="?model=1">switch to model 1</a>
<div id="output">
{% for item in output %}
<div id="{{item}}">
{{item}}
</div>
{% endfor %}
</div>
</body>
</html>
I tried to put the div#output into a separate template output.html and modified the views.py like so:
def test(request, template='test.html'):
if request.GET.get('model'):
output=model1.objects.all()
else:
output=itertools.chain(
model1.objects.all(),
model2.objects.all(),
model3.objects.all()
)
if request.is_ajax(): template='output.html'
return render_to_response(template, {'output':output})
But everytime I click the link, the whole page is refreshed (with the new values from model1).
Opera returns just the output.html
Been struggling with this for more than 3 days, Im new into Ajax and this is getting very confusing for me.
I hope someone can shed some light!
First, make sure that your view works and that you're getting the expected HTML output when accessing the url directly (you might also want to comment out if request.is_ajax() temporarily).
Then, try replacing the content of the #output div using jQuery.html() method in your ajax call. Here is an example with some animation:
$.ajax({
...
success: function( returnedData ) {
$("#output").css("color", "red").fadeOut(500, function() {
$("#output").html(returnedData);
$(this).css("color", "green").fadeIn(500);
});
}
Also, try monitoring your ajax call using Firebug/Chrome Developer Tools - both tools will allow you to quickly determine the issue.
Thanks to Daniel Rosman for the heads-up I had to prevent the default action of the a#switch. It works like butter now!
Here is the initial question: how to access jQuery.ajax() get parameters in Django views