I have a profile page with user posts. People can like/dislike the posts. It works well but it reloads the page, that is why I am implementing AJAX.
The route goes like this.
Inside the profile view is the "like POST" request ending with a
data = {
'likes':post.likes.all().count()
}
return JsonResponse(data,safe=False)"
When clicking on the like button, I can see the data on a blank page if I want to. So I know it is receiving it.
Unfortunately, when using AJAX, instead of returning the data. it returns the profile view's
return render(request, "profile.html", context)
Here is my AJAX code
const post_id = $(this).attr('id')
const likeText = $( `.like_button${post_id} `).attr('name')
const trim = $.trim(likeText)
const url = $(this).attr('action')
let res;
const likes = $(`.like_count${post_id}`).text() || 0
const trimCount = parseInt(likes)
$.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken':$('input[name=csrfmiddlewaretoken]').val(),
'post_id':post_id,
},
success: function(data){
console.log('success', data)
},
error: function(data){
console.log('error', data)
}
})
Any help would be much appreciated. First time using AJAX, so as much details would be appreciated.
Not really surprising it's returning HTML since that's exactly what you're returning in the view: rendered HTML. If you want JSON you need then you want a JSONResponse object.
https://docs.djangoproject.com/en/4.1/ref/request-response/#jsonresponse-objects
So, instead of:
return render(request, "profile.html", context)
which will take the profile.html, inject the values from context and send you that as html, you should do something like:
response = JsonResponse({"mydata": "goes here", "some_more": data})
You can then parse this as JSON in your AJAX code. If it's the case that the context dictionary contains all the data you need and that is what you want, you can just swap out that one line:
response = JsonResponse(context)
Edit: To address the question in the comment. Suppressing the default form response in the frontend is not a Django thing, it's done with JS on the event using something like:
e.preventDefault()
See here for info: https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault
I'm using ajax, python, Django, HTML, and javascript for my project.
I'd like to know, if there is a p in my HTML file like,
<p class='text_box', id='tbox'>
{{ text_variable_from_python }}
</p>
<input class='input_box', id='ibox', type='text'>
And if I'd input some text into the input box, make a simple ajax request with the "text" variable and get an output from the server, which I would update on the views.py as,
def main(request):
if request.method == 'POST':
new_text = request.POST['text']
context = {'text_variable_from_python': new_text}
else:
context = {'text_variable_from_python': 'You can change me!'}
print(context)
return render(request, 'Main.html', context=context)
My question is, how do I send the data dynamically from the server to appear on client's webpage using ajax and python in between the two?
Using my method, I can only see "You can change me!" on the webpage or nothing at all. No matter how many differing prompts I give, further changes do not show on the webpage.
EDIT:
My ajax code for sending the variable.
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<script>
function update_dialogue() {
$.ajax({
type: "json",
url: "update_text",
success: function(data) {
document.getElementById("tbox").value = data['text_variable_from_python'];
}
});
}
My ajax code for recieving the variable.
<script>
function getInputValue() {
let inputVal = document.getElementById("ibox").value;
document.getElementById("ibox").value = '';
$.ajax({
type:'POST',
url: 'main',
data: {csrfmiddlewaretoken: "{{ csrf_token }}",
'text': inputVal,}
});
}
</script>
(sorry for my bad English)
Hello. I know partly how ajax is used with Django. but I have some problems. Some of them are: how to render a template with ajax? How to send Django to template with ajax? I searched the internet but I couldn't find exactly what I wanted.
I would be glad if you could also recommend a detailed resource on the use of ajax and Django. (free:( ).please help me guy.thanks now.
First you have to create instances in your Django's views.py file which returns the data you wanna display in template.
Then you need to create an ajax function inside the template. Here is a basic ajax function that can be modified to your needs:
<script>
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML = this.responseText;
}
};
xhttp.open("GET", "demo_get.asp", true);
xhttp.send();
}
</script>
What it does is reach out to the source of data in your case it will probably be the instances in views.py. "readyState == 4" tells you the data load is complete, while "this.status == 200" tells you if the request is successful.
The question on how to display the data depends on you and the type of data.
I am getting a list containing books, I have to make filter button to categorise it, Right now I am passing argument in the link "?filter=2" with each button click. But this requires reloading the page.
In the get function
self.book_type = request.GET.get("book_type")
in the get_queryset
return qs.filter(book_filter=self.book_type)
HTML
Simply redirecting to the page with a query added to the link
containing ?book_type=" anything"
you have to had a view like this:
from django.http import JsonResponse
def get_books(request):
book_type = request.GET.get("book_type")
res = qs.filter(book_filter=self.book_type)
return JsonResponse({"data": res})
Then create url in your template like this(it creates a javascript varibale contains url to get_books):
<script> book_get_url = "{% url 'route_name_to_get_books_from_urls.py' %}";</script>
now you can use the book_get_url variable in your javascript like this:
$.ajax({
url: book_get_url,
type: "GET",
"data": {
book_type: here is your book_type as a number
},
success: function (data) {
//here you have your books in `data.data` in json fromat
}
)};
There are LOTS of post and pages discussing the use of Django and AJAX, and I've read hundreds over the past day or so looking for the answer to this question. A quick overview:
May of the examples show a hard-coded URL like this:
$.post("/projects/create/", {"name" : name}, function(data) {...
or some use the URL template tag, but with no parameters:
$.post("{% url create_project %}", {"name" : name}, function(data) {...
However, I'd like to include a Django-style parameter in a URL. Here's my url definition:
url(r'ajax/entity_name/(?P<pk>\w+)/$',EntityAjaxView.as_view(),name='entity_name'),
Yes, I'm using a class based view, and it is based on DetailView. This view looks by default for a pk value to be provided in the URL, and in a normal template I would use:
{% url entity_name id_number %}
to provide a link. In my code, I want to grab the value entered in an input box for the pk value. Here is a snippet of my JavaScript (which doesn't work):
var id_number = $('#id_endowmententity_set-' + rownum + '-id_number').val()
$.ajax({
type: "GET",
url: '{% url entity_name id_number %}',
So, my question is, can I use the URL template tag with a value from an input box?
(I know that I could use POST instead of GET and pass the id_number in the POST data, but that won't work well with the DetailView.)
Django is a server-side application. Javascript is client-side. Django templates get rendered on the server, so {% url entity_name id_number %} is evaluated on the server side, and then it's value is returned to the client. Just because of this, it's impossible for you to combine Django templates with javascript. However there are couple of things you can do to solve your problem.
Since you are making an ajax call, and the ajax call depends on some user input, usually the best route for the client to send any type of user input to the server is by either using querystring (thing after ? in the URL) or by sending a POST data. So the simplest thing is to change your your url not to include the pk in the url, but for the view to get that as part of GET or POST data.
url(r'ajax/entity_name/$', EntityAjaxView.as_view(), name='entity_name'),
and the view (sorry I'm not familiar with class based views):
def entity_name(request):
pk = request.GET.get('pk')
...
That seems to me to be the most elegant solution. If however you absolutely need to construct the url on the client side, you can generate a template url on the server side and then replace whatever parts you need on the client side to get the full url. This however requires more maintenance and therefore is more error prone. Simple js example of this approach:
var id_number = $('#id_endowmententity_set-' + rownum + '-id_number').val(),
url = '{% url entity_name 0 %}'.replace('0', id_number);
$.ajax({
type: "GET",
url: url,
...
});
It is possible to set an Ajax url on the element you are selecting using an attribute and it will behave like Django urls. Importantly, you can even access the url in Javascript file. I use it a lot
HTML
<div class="card-body" id="js-products" data-url="{% url 'chart-data' %}">
<div class="chart-area">
<canvas id="testChart"></canvas>
</div>
</div>
Note: the data-url attribute set on parent div
JAVASCRIPT
$(document).ready(function () {
var endpoint = $("#js-products").attr("data-url");
var defaultData = [];
var labels = []
$.ajax({
method: 'GET',
url: endpoint,
success: function (data) {
labels = data.labels
defaultData = data.data_default
setChart()
},
error: function (error_data) {
console.log(error_data)
}
})
function setChart() {
var ctx = document.getElementById('testChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'line',
responsive: true,
data: {
labels: labels,
datasets: [{
label: 'Monthly Performance',
data: defaultData,
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
});
DJANGO VIEWS
Am using django rest framework class view but you can use either of function or class based view
class ChartData(APIView):
authentication_classes = []
permission_classes = []
def get(self, request, format=None):
labels = ['Products', 'User', 'May']
data_default = [SeedProduct.objects.all().count(),
User.objects.all().count(), 4]
data = {
'labels': labels,
'data_default': data_default,
}
return Response(data)
DJANGO URLS:
import the view class from views
path('api/chart/data', views.ChartData.as_view(), name="chart-data"),
It's pretty time consuming to go round trip to a server just to fetch a URL. The best strategy to keep URLs dry and avoid this is to generate javascript that emulates Django's native url reverse function and then serve that code statically with the rest of your client side JS.
django-render-static does just that.
This worked for me.
my URL was:
path('myurl/<str:type>', views.myfunction, name='myfunction')
my views.py file:
def myfunction(request,type):
return render(request, "payment.html", context)
In my template, I solved the issue by:
<button type="button" class="btn"
onclick="myfunction('forward');">My Button Name
</button>
<script>
function myfunction(type){
let url = "{% url 'appName:myfunction' 'ok' %}".replace('ok', type);
$.ajax({
method: 'POST',
url: url,
data: {
csrfmiddlewaretoken: '{{ csrf_token }}'
}
});
}
</script>