I'm getting a 500 error on the submission of an ajax call. I was wondering if you could help me figure out why.
Please note that the csrf_token is added to the data on a seperate javascript (using code under the 'AJAX' section of this page: https://docs.djangoproject.com/en/dev/ref/csrf/#ajax). My understanding is that if there is a problem with the csrf_token, a 403 error would be thrown.
Template
<form class="userorder" method='POST' action='.' data-url='{{ request.build_absolute_uri|safe }}'>
{{ form.non_field_errors }}
{% csrf_token %}
{{ form.couponcode.errors }}
<div class="coupon_message"></div>
<div id="couponcodevalue">{{form.couponcode}}</div>
<div id="couponcodeapply">Apply</div>
<button type="submit">Submit</button>
</form>
Javascript
<script>
$("#couponcodeapply").click(function(){
var coupon = $("#id_couponcode").val()
var data = {coupon: coupon,}
$.ajax({
type: "POST",
url: "/getcoupon/",
data: data,
success: function(data) {
$("#coupon-message").text("Coupon Added")
},
error: function(response, error) {
$("#coupon-message").text("Coupon Not Added")
}
})
});
</script>
views.py
def getcoupon(request):
print("I am in getcoupon")
if request.is_ajax():
message = "hi"
data = {
'message': message,
}
return JsonResponse(data)
Error in Console (Chrome)
jquery.min.js:4 POST http://localhost:8000/getcoupon/ 500 (Internal Server Error)
send # jquery.min.js:4
ajax # jquery.min.js:4
(anonymous) # (index):1636
dispatch # jquery.min.js:3
r.handle # jquery.min.js:3
Is there any way to get additional detail on why this 500 code is being thrown?
Thanks!
I failed to import Jsonresponse into the view!
from django.http import JsonResponse
Related
I have simple form
class TimeForm(forms.Form):
time = forms.TimeField()
date = forms.DateField()
def clean_date(self):
time = self.cleaned_data['time']
date = self.cleaned_data['date']
date_time = datetime.combine(date, time)
if datetime.now() > date_time:
raise ValidationError("datetime error")
return start_date
with class based view
class TimeView(View):
#staticmethod
def post(request):
form = TimeForm(request.POST)
if form.is_valid():
# do something
json_data = json.dumps({'some_record': value})
else:
json_data = json.dumps({'errors': form.errors})
return HttpResponse(json_data, content_type='application/json')
In html I have standard form with submit connected do ajax
<form action="/time_url/" method="POST" id="time_form">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit">
</form>
<script>
$('#time_form').submit(function(event) {
event.preventDefault();
$.ajax({
type: "POST",
url: '/time_url/',
dataType: 'json',
data: $(this).serialize(),
success: function(data, textStatus, jqXHR){
alert('yay');
}
})
});
</script>
and I'd like to be able to submit this form without page reload. Everything seems to work perfectly but success function of ajax is not triggered, instead page is redirected to /time_url/ with json data. It doesn't matter wheter form is valid nor not, it's always redirected.
I've tried also with
return JsonResponse(form.errors.get_json_data())
instead of
return HttpResponse(json_data, ...)
as suggested here Django form submit with ajax but without success.
I'm new to javascript but for me it looks like problem with ajax, since proper data is served by server.
Thanks for any tips.
When I use ajax to submit a comment form in Django,the page will redirect to a blank page shows me the success data:
{"status":"success", "msg":"添加成功"}
,but not stay in current page.I want the page stay in current page and show me the new comment.
Here is my update_comment view:
def update_comment(request, news_pk):
news = get_object_or_404(News, id=news_pk)
comment_form = CommentForm(request.POST or None)
if request.method == 'POST' and comment_form.is_valid():
if not request.user.is_authenticated:
return render(request, 'login.html', {})
comments = comment_form.cleaned_data.get("comment")
news_comment = NewsComments(user=request.user, comments=comments, news=news)
news_comment.save()
# return redirect(reverse('news:news_detail', kwargs={'news_pk': news.id}))
return HttpResponse('{"status":"success", "msg":"添加成功"}', content_type='application/json')
else:
return HttpResponse('{"status":"fail", "msg":"添加失败"}', content_type='application/json')
Here is my ajax:
$(document).on('submit', 'comment_form', function(e){
e.preventDefault();
$.ajax({
cache: false,
type: "POST",
url:"{% url 'operation:update_comment' news.id %}",
data:{'news_pk':{{ news.id }}, 'comments':comments},
async: true,
beforeSend:function(xhr, settings){
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(data) {
if(data.status == 'fail'){
if(data.msg == '用户未登录'){
window.location.href="login";
}else{
alert(data.msg)
}
}else if(data.status == 'success'){
window.location.reload();//refresh current page.
}
},
});
});
Here is my form:
<form id="comment_form" action="{% url 'operation:update_comment' news.id %}" method="POST" >
{% csrf_token %}
<textarea id="comment_textarea"name="comment"></textarea>
<input type="submit" value="Submit"> </input>
</form>
Finally I made it!Thanks Lord!Very excited!
I have Three major issues in my previous code.
First:Since the ajax will post the news_pk to the view update_comment,so I don't need add news_pk in this view's url and template(in the url of <form> tag and the url in the ajax),so I removed them,or the data will still pass through Form but not ajax.
Second:My binding is incorrect,I have the click handler on the form it should be a submit handler. If I was binding it to a button then I'd use click a handler.Ajax not work in Django post
But for this part I'm still a some confused,between the button summit way and form submit way.
The third issue is I mistaked 'comments' and 'comment'.'comment' is the name attribute of <textarea> ,through which forms.py gets the data.
comments is defined by ajax through var comments = $("#js-pl-textarea").val(), so in the view I need use comments = request.POST.get("comments", "") but not comment,that's the reason why 'post failed'.
Following is my code.
Here is the ajax:
$("#comment_form").submit(function(){
var comments = $("#js-pl-textarea").val()
$.ajax({
cache: false,
type: "POST",
url:"{% url 'operation:update_comment' %}",
data:{'news_pk':{{ news.pk }}, 'comments':comments},
async: true,
beforeSend:function(xhr, settings){
xhr.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
},
success: function(data) {
if(data.status == 'fail'){
if(data.msg == '用户未登录'){
window.location.href="login";
}else{
alert(data.msg)
}
}else if(data.status == 'success'){
window.location.reload();//refresh current page.
}
},
});
return false;
});
Here is my udate_comment view:
#login_required
def update_comment(request):
news_pk = request.POST.get("news_pk", 0)
comments = request.POST.get("comments", "")
if int(news_pk) > 0 and comments:
news_comments = NewsComments()
news = News.objects.get(id=int(news_pk))
news_comments.news = news
news_comments.comments = comments
news_comments.user = request.user
news_comments.save()
return HttpResponse('{"status":"success", "msg":"添加成功"}', content_type='application/json')
else:
return HttpResponse('{"status":"fail", "msg":"添加失败"}', content_type='application/json')
Here is my form in template:
<form id="comment_form" action="{% url 'operation:update_comment'%}" method="POST" >
{% csrf_token %}
<textarea id="js-pl-textarea"name="comment"></textarea>
<input type="submit" value="Submit"> </input>
</form>
I really appreciate everyone's reply!With your reply I figured out these issue step by step!
I have something similar in my project. Its a script to like a song. I'm just gonna put the relevant codes here.
The ajax script. I put this script in a separate file named like_script.html. I call it in a template using django template include
<script>
$('#like').click(function(){
$.ajax({
type: "POST",
url: "{% url 'song:like_song' %}",
data: {'pk': $(this).attr('pk'), 'csrfmiddlewaretoken': '{{ csrf_token }}'},
dataType: "json",
success: function(response) {
alert(response.message);
},
error: function(rs, e) {
alert(rs.responseText);
}
});
})
</script>
The django view
import json
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from django.views.decorators.http import require_POST
#login_required
#require_POST
def song_like_view(request):
if request.method == 'POST':
user = SiteUser.objects.get(user=request.user)
pk = request.POST.get('pk', None)
song = get_object_or_404(Song, pk=pk)
if song.likes.filter(pk=user.pk).exists():
song.likes.remove(user)
song.like_count = song.likes.count()
song.save(update_fields=['like_count'])
message = "You unstarred this song.\n {} now has {} stars".format(song.title, song.like_count)
else:
song.likes.add(user)
song.like_count = song.likes.count()
song.save(update_fields=['like_count'])
message = "You starred this song.\n {} now has {} stars".format(song.title, song.like_count)
context = {'message' : message}
return HttpResponse(json.dumps(context), content_type='application/json')
The url
urlpatterns = path("like/", views.song_like_view, name='like_song'),
The template where the script is called
<a class="btn btn-sm btn-primary" href="" id="like" name="{{ song.pk }}" value="Like"></i> Unstar</a>
{% include 'like_script.html' %}
Same button for like and unlike. I hope you can follow the logic to make yours right. Notice that in your view you don't need to include the pk. Just get it from the POST data pk = request.POST.get('pk', None)
all! Can u please help me? I have a small problem. When i click button, When I click on a button, a new object should be created without reloading the page. Only one parameter is required to create an object.
The problem is that when you click the object is created (the new object is displayed in the admin panel), but in the console js there is an error:
Failed to load resource: the server responded with a status of 500 (Internal Server Error)
JS:
function initBuyButton(){
$('.button-buy').click(function(e){
e.preventDefault();
var test = $(this);
var smartphone_id = test.data("smartphone_id");
var url = test.attr("action");
basketUpdating(smartphone_id, url);
});
}
function basketUpdating(smartphone_id, url){
var data = {};
var csrf_token = $('#form_buying_product [name="csrfmiddlewaretoken"]').val();
data["csrfmiddlewaretoken"] = csrf_token;
data.smartphone_id = smartphone_id;
$.ajax({
url: url,
type: 'POST',
data: data,
cache: true,
});
}
$(document).ready(function(){
initBuyButton();
});
View:
def basket_adding(request):
"""Add new smartphone to basket."""
data = request.POST
smartphone_id = data.get('smartphone_id')
SmartphoneInBasket.objects.create(smartphone_id=smartphone_id)
return True
HTML:
<form id="form_buying_product" > {% csrf_token %}
{% for sm in smartphones %}
...
<input type="submit" action="{% url 'basket_adding' %}" class="button-
buy" data-smartphone_id = "{{ sm.id }}" value="Buy">
{% endfor %}
</form>
As mentioned in the comments, a view needs to return an HttpResponse. If you want, it can be n empty:
return HttpResponse()
You need to include the csrf token as a header.
var csrftoken = $("[name=csrfmiddlewaretoken]").val();
$.ajax({
url: url,
type: 'POST',
headers:{
"X-CSRFToken": csrftoken
},
data: data,
cache: true,
});
Because an error 500 is that your permission gets denied to send the data.
I have the following helper functions defined:
import json
def json_response(request, val, **kw):
"""Return a json or jsonp response.
"""
if request.GET.get('callback'):
return jsonp(request.GET['callback'], val, **kw)
else:
return jsonval(val, **kw)
def jsonval(val, **kw):
"""Serialize val to a json HTTP response.
"""
data = dumps(val, **kw)
resp = http.HttpResponse(data, content_type='application/json')
resp['Content-Type'] = 'application/json; charset=UTF-8'
return resp
def jsonp(callback, val, **kw):
"""Serialization with json callback.
"""
data = callback + '(%s)' % json.dumps(val, **kw)
return http.HttpResponse(
data,
content_type='application/javascript; charset=utf-8'
)
with those defined your view can return a json object (to your ajax call):
def basket_adding(request):
"""Add new smartphone to basket."""
...
return json_response(request, True)
it's common practice to return an object though, so perhaps:
return json_response(request, {"status": True})
I am not able to get the input text field data with id city_name from the form via jQuery-Ajax method.
The error that I keeps getting is "NetworkError: 403 FORBIDDEN - http://127.0.0.1:8000/dashboard".
I know how to get the data using hidden field type, but that option cannot be used here and moreover, getting data from hidden field is now an outdated method. So, how can I get data using Django-AjaxJquery method.
HTML
<form type = "POST">
{% csrf_token %}
<input type="text" placeholder = "Enter City Name" id = "city_name">
<input type="button" value = "On" id="on">
<input type="button" value = "Off" id="off">
</form>
JS File
$(function(){
$("#on").click(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "dashboard",
data : {
'city_name' : $("#city_name").val(),
},
});
});
});
View.py
#login_required
def dashboard(request):
ctx = {}
if request.is_ajax():
city_name = request.POST['city_name']
print city_name
return render_to_response('dashboard/dashboard.html',ctx, context_instance = RequestContext(request))
urls.py
urlpatterns = patterns('',
url(r'^dashboard$','apps.dashboard.views.dashboard', name = 'llumpps_dashboard'),
)
It is missing the CSRF token in the request.
You can either use #csrf_exempt decorator for your view like:
#login_required
#csrf_exempt
def dashboard(request):
...
Or send the token along with the request:
$.ajax({
type: "POST",
url: "dashboard",
data : {
'csrfmiddlewaretoken': $('input[name="csrfmiddlewaretoken"]').val();
'city_name' : $("#city_name").val(),
},
complete: function () {
// do whatever here
}
});
Read more about CSRF and AJAX in Django here: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
Hope it helps.
In my app, there are several categories of data that need to be sent from client browser to server.
the back end is in Django. I am trying to using Ajax to POST data to the view function in Django, and then return something to client. The codes I've tried are as follows:
In Django urls.py:
(r'^testPost/', testPost),
Django View function:
def testPost(request):
print request
if request.method == 'GET':
rID = request.GET['rID']
rName = request.GET['rName']
elif request.method == 'POST':
rID = request.POST['rID']
rName = request.POST['rName']
return HttpResponse("ID: " + str(rID) + " and Name: " + str(rName))
Front-end AJAX call (ExtJS 3.3):
Ext.Ajax.request({
url: 'XXXX/testPost/?',
method: 'POST',
jsonData: Ext.encode({
"rID": 1333,
"rName": 'test'
}),
headers: {
'Content-Type': 'application/json'
},
success: function (response, opts){
console.log(response.responseText);
},
failure:function (response, opts){
console.log(response.responseText);
}
});
It seems something is wrong with URL setting. got an error response:
Some unexpected error occurred. Error text was: HTTP Error 403: FORBIDDEN
UPDATE:
1. based on ldiqual's advice, put
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
in the view script
changed ExtJS ajax request code from using jsonData to params:
params: {
"rID": 1333,
"rName": 'test'
}
issue is solved for my case.
For ajax POSTing, you'll need CSRF token, and it's unwise to simply disable it with #csrf_exempt since it defeats the purpose. If you don't want CSRF protection, then remove 'django.middleware.csrf.CsrfViewMiddleware' from MIDDLEWARE_CLASSES.
The Django docs provide a jQuery function that will automatically add the token to all ajax requests: https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax
I don't have any experience with ExtJS, but you'll want to find an equivalent. Here are some snippets you could look at:
https://stackoverflow.com/a/5485616/338903
http://djbook.ru/examples/22/
http://www.sencha.com/forum/showthread.php?134125-Django-1.3-Login-with-ExtJS-4-and-CSRF
In your template file (assume that you use jQuery library):
<form id="MyForm" action="." method="POST">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" class="default" value="Save" onclick="PostThisToAjax(jQuery("#MyForm").serialize()); return false;" />
</form>