I am trying to render a Json Response on a html site using AJAX but i keep getting the error:
Uncaught ReferenceError: data is not defined
at HTMLDocument.<anonymous
JsonResponse in Question:
["[53.50119612705815, -1.1270833894501477] -> [53.34474, -3.01101]", "[53.50119612705815, -1.1270833894501477] -> [53.34474, -3.01101]", "[52.04061648544843, -0.6655072691644374] -> [51.90829, -0.5127]", "[52.04061648544843, -0.6655072691644374] -> [51.90829, -0.5127]", "[52.04061648544843, -0.6655072691644374] -> [51.90829, -0.5127]", "[53.50119612705815, -1.1270833894501477] -> [53.42705, -0.94339]"]
Html file with AJAX and JS:
<div class="'row">
<div id="test">
<h1> Test </h1>
</div>
</div>
{% endblock %}
{% block js %}
<script>
$(document).ready(function(){
$.ajax({
type: 'POST',
dataType: 'json',
url: '/network/dispatch_data/',
data: data,
success: function(response) {
console.log(response);
$('#test').append(response.data);
}
});
});
</script>
{% endblock %}
When i inspect element in my browser, the error points to the data: data being the source of the error. Any idea what i'm doing wrong? I can view the url perfectly with the json response but making it show with ajax is proving a problem
You are sending data as the body of your request, but first you have to defined the object you are sending to API
<div class="row">
<div id="test">
<h1> Test </h1>
</div>
</div>
{% endblock %}
{% block js %}
<script>
const data = {
bar: [1, 2, 3],
foo: false
}
$(document).ready(function () {
$.ajax({
type: 'POST',
dataType: 'json',
url: '/network/dispatch_data/',
data: data,
success: function (response) {
console.log(response);
$('#test').append(response.data);
}
});
});
</script>
{% endblock %}
Related
I have several ajax scripts in the base body django template. I want to run them in a separate js file, but the scripts do not work from a file.
My script in the body template (this is a working code.):
<!--Add product to the cart after press Add button-->
<script>
$(document).on('click', '#add-button', function (e){
e.preventDefault();
var prodid = $('#add-button').val();
$.ajax({
type: 'POST',
url: '{% url "add_cart" %}',
data: {
product_id: $('#add-button').val(),
quantity: $('#qty').val(),
csrfmiddlewaretoken: '{{csrf_token}}',
action: 'POST'
},
success: function (json) {
document.getElementById('cart_icon_count').innerHTML = json.qty;
},
error: function(xhr, errmsg, err) {}
});
})
</script>
Than delete script from body and copy in js file:
my_js.js
$(document).on('click', '#add-button', function (e){
e.preventDefault();
var prodid = $('#add-button').val();
$.ajax({
type: 'POST',
url: '{% url "add_cart" %}',
data: {
product_id: $('#add-button').val(),
quantity: $('#qty').val(),
csrfmiddlewaretoken: '{{csrf_token}}',
action: 'POST'
},
success: function (json) {
document.getElementById('cart_icon_count').innerHTML = json.qty;
},
error: function(xhr, errmsg, err) {}
});
})
and in the body:
<script src="{% static 'js/my_js.js' %}"></script>
The usual java script function works this way, but for some reason this script does not.
Any ideas for running one or more of these scripts from a separate file?
Thank's qrsngky - you helped me figure it out 50% and guided me to the right solution!
{% url "add_cart" %} I replaced with "/cart/add_cart/".
Error 403 Forbidden - the problem was in csrftoken.
I add in my base.html
<script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
and in 'js/my_js.js' add csrfmiddlewaretoken: window.CSRF_TOKEN
Similar I put {% url "add_cart" %} in variable in the body.html.
And everything worked!
Here is a div that I append in AJAX with a script (at the bottom of the TWIG file) :
<div>
{% for vote in proposal.votes %}
{% if app.user == vote.user %}
<a href="{{ path('vote_delete',{'proposal' : proposal.id, 'vote' : vote.id}) }}"
class="btn btn-light ml-1 btn-sm">
</a>
{% endif %}
{% endfor %}
</div>
If I then click on the freshly appended button, it returns an error because the ID "vote.id" is still 0 until I reload the page and the ID gets found...
Is there a way to trigger the for loop without reloading the page to get the ID directly after its creation? Is it linked with "async" or any "ready" function?
EDIT :
The script that appends the div #deleteVote when I vote :
$(document).on('click', '.votedFullAgreement', function (event){
event.preventDefault();
$.ajax({
url: '{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}',
type: 'POST',
dataType: 'html',
success: function (){
if( $('#deleteVote').length === 0 ) {
//The whole HTML of the div
},
error: function (resultat, statut, erreur) {
console.error(erreur);
}
});
});
The #deleteVote that gets appended, with the url of the "deleteVote" function (which needs to know the ID of the vote to delete) :
$(document).on('click', '.deleteVote', function (event){
event.preventDefault();
$.ajax({
url: '{{ path('vote_delete', {'slug' : slug, 'proposal' : proposal.id, 'vote' : vote.id }) }}',
type: 'POST',
dataType: 'html',
success: function (){
$('#deleteVote').slideUp();
},
});
});
As I've mentioned in the comments, you can't pass a javascript directly to twig, as twig is rendered serverside. One way to solve this is to calculate all the path beforehand:
{% for vote in proposal.votes %}
...
<button type="button" class="votedFullAgreement" data-path="{{ path('vote_add', {'slug' : slug, 'proposal' : proposal.id, 'userVote' : 'votedFullAgreement', 'user' : app.user.id }) }}">Add vote</button>
...
{% endfor %}
Now you can access the path directly in javascript
$(document).on('click', '.votedFullAgreement', function (event){
event.preventDefault();
$.ajax({
url: $(this).data('path'),
type: 'POST',
dataType: 'html',
success: function (){
if( $('#deleteVote').length === 0 ) {
//The whole HTML of the div
},
error: function (resultat, statut, erreur) {
console.error(erreur);
}
});
});
You could also make an extra request to a controller to generate the path, but this would mean you would need to pass all the variables, e.g. slug, app.user.id, ...
More information on how to generate a path inside a controller can be found here
I just started with ajax but can't seem to find the fix for this. I think it might have to do with the comment_id vs the blog_id. (followed this tutorial: https://www.youtube.com/watch?v=VoWw1Y5qqt8&list=PLKILtxhEt4-RT-GkrDkJDLuRPQfSK-6Yi&index=39&ab_channel=AbhishekVerma).
This is what my views.py looks like
def like_comment(request):
comment = get_object_or_404(Comment, id=request.POST.get("comment_id"))
blog = get_object_or_404(BlogPost, id=request.POST.get("blog_id"))
comments = Comment.objects.filter(post=blog, reply=None)
if request.user in comment.likers.all():
comment.likers.remove(request.user)
else:
comment.likers.add(request.user)
context = {
"comments": comments,
"blog_post": blog,
"body": markdown2.markdown(blog.body),
"comment_form": CommentForm(),
}
if request.is_ajax():
html = render_to_string('blog/like_section.html',
context, request=request)
return JsonResponse({'form': html})
This is a snippet of my HTML
{% if request.user.is_authenticated %}
<form action={% url 'like_comment' %} method="POST">
{% csrf_token %}
{% if user in comment.likers.all %}
<input type="hidden" name="blog_id" value=" {{ blog_post.id }}">
<button type="submit" id="like" name="comment_id" value="{{ comment.id }}">Like</button>
{% else %}
<input type="hidden" name="blog_id" value=" {{ blog_post.id }}">
<button type="submit" id="like" name="comment_id" value="{{ comment.id }}">Dislike</button>
{% endif %}
{% else %}
<div><small class="comment_time">Login to Like</small></div>
{% endif %}
</form>
</div>
<small class="comment_time">{{ comment.total_likes }}
Likes</small>
And this is the javascript:
$(document).ready(function (event) {
$(document).on('click', '#like', function (event) {
event.preventDefault();
var pk = $(this).attr('value');
$.ajax({
type: "POST",
url: '{% url "like_comment" %}',
data: { 'blog_id': pk, 'csrfmiddlewaretoken': '{{ csrf_token }}' },
dataType: 'json',
success: function (response) {
$('#like_section').html(response['form'])
console.log($('#like_section').html(response['form']));
},
error: function (rs, e) {
console.log(rs.responseText);
},
});
});
});
I'm getting the following error:
Picture
I would start to check if the request header contains HTTP_X_REQUESTED_WITH='XMLHttpRequest'. You can do that with the debug function of the browser (e.g. firefox). Maybe your JS library does not send this header.
see the Django documentation:
https://docs.djangoproject.com/en/1.11/ref/request-response/#django.http.HttpRequest.is_ajax
def is_ajax(self):
return self.META.get('HTTP_X_REQUESTED_WITH') == 'XMLHttpRequest'
HttpRequest.is_ajax():
Returns True if the request was made via an XMLHttpRequest, by checking the HTTP_X_REQUESTED_WITH header for the string 'XMLHttpRequest'. Most modern JavaScript libraries send this header. If you write your own XMLHttpRequest call (on the browser side), you’ll have to set this header manually if you want is_ajax() to work.
If a response varies on whether or not it’s requested via AJAX and you are using some form of caching like Django’s cache middleware, you should decorate the view with vary_on_headers('X-Requested-With') so that the responses are properly cached.
Having a tough time with this. I'm sending some data via Ajax to my Flask server route where it is being processed, with hopes to then render a new template with the processed data. The data seems to be flowing fine from my Javascript to my Flask server. (I am using JSGlue for Flask.url_for.) But as soon as it gets to "return render_template" it just dies. I get no traceback errors or anything. I've tried print() and console.log all over the place to get some kind of idea of what is killing it, but so far I've come up empty. Am I missing something obvious?
mypage.js
let c_list = [1,2,3....];
$.ajax({
url: Flask.url_for('get_genres'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(c_list),
success: function (data) {
console.log(data);
}
})
init.py
#app.route('/get_genres', methods=["GET", "POST"]
def get_genres():
if request.method == "POST":
categories = request.json
c = Querybuilder()
genres = c.genres_from_c(categories)
return render_template("genres.html", genres=genres)
index.html
<head>
{{ JSGlue.include() }}
</head>
<body>
{% block body %}
{% endblock %}
</body>
genres.html
{% extends "index.html" %}
{% block body %}
<div class="genre_list">
{% for genre in genres %}
<a href="#" src="{{ genres[genre] }}" class="unclicked" onclick="toggleClicked(this)">
<p>{{ genre }}</p></a>
{% endfor %}
NEXT
</div>
{% endblock %}
After A LOT of digging around, I finally managed to find a solution to this issue. Adding a success function to the ajax call that redirects to another route.
mypage.js
$.ajax({
url: Flask.url_for('genre_picks'),
type: "POST",
dataType: 'json',
contentType: 'application/json',
data: JSON.stringify(genres),
success: function(response) {
window.location.href = response.redirect
}
});
init
#app.route('/genre_picks', methods=["POST", "GET"])
def genre_picks():
if request.method == "POST":
genres = request.json
return jsonify({'redirect': url_for("example", path=genres)})
#app.route('/example/<path>')
def example(path):
genres = path
return render_template("example.html", genres=genres)
I'm trying to implement a like functionality in my Django app using AJAX but, when I try to do that I'm getting an POST http://localhost:8000/forum/like/ 404 (Not Found). All I wanna do is to add/remove users from the likes list without refreshing the entire page.
views.py
#require_POST
def toggle_like(request):
if request.method == "POST":
user = request.user
slug = request.POST.get('slug', None)
question = get_object_or_404(Question, slug=slug)
if question.likes.filter(id=user.id).exists():
question.likes.remove(user)
else:
question.likes.add(user)
context = {'likes-count': question.likes.count}
return HttpResponse(json.dump(context), content_type='application/json')
urls.py
from django.urls import path
from . import views
app_name = 'forum'
urlpatterns = [
path('like/', views.toggle_like, name='toggle-like'),
]
question.html
{% block javascript %}
<script>
$('#like').click(() => {
$.ajax({
method: 'POST',
url: "{% url 'forum:toggle-like' %}",
data: {
'slug': $(this).attr('name'),
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
dataType: 'json',
success: (response) => {
alert(response.message);
},
error: (response, error) => {
alert(response.responseText);
}
})
})
</script>
{% endblock %}
{% block content %}
<p>Likes: {{ question.likes.count }} <input type="button" id="like" name="{{ question.slug }}" value="Like" /></p>
{% endblock %}