500 (Internal Server Error) AJAX Django - ajax

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})

Related

Django Ajax Modify avatar failed

I'm trying to use Django Ajax to Modify user's avatar, but it doesn't work.There is no any error information, just doesn't work.
Here is my form in template:
<form class="clearfix" id="jsAvatarForm" enctype="multipart/form-data" autocomplete="off" method="post" action="{% url 'users:image_upload' %}" target='frameFile'>
<img id="avatarShow" src="{{ MEDIA_URL }}{{ request.user.image }}"/>
<input type="file" name="image" id="avatarUp" class=""/>
<button type="submit">Modify Avatar</button>
{% csrf_token %}
</form>
Here is my Ajax:
$("#jsAvatarForm").submit(function(){
var image = $("#avatarShow").val()
$.ajax({
cache: false,
type: "POST",
url:"{% url 'users:image_upload' %}",
data:{'user_pk':{{ user.pk }}, 'image':image},
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 views.py:
class UploadImageView(LoginRequiredMixin, View):
def post(self, request):
user_pk = request.POST.get("user_pk", 0)
image = request.FILES.get('image')
user_change = UserProfile()
user_change.id = user_pk
user_change.image = image
user_change.save
return HttpResponse('ok')
Actually I also have a forms.py but I don't know how to use it with ajax:
class UploadImageForm(forms.ModelForm):
class Meta:
model = UserProfile
fields = ['image']
Here is my user model, note:I have rewrote my own USER:
class UserProfile(AbstractUser):
image = models.ImageField(upload_to="image/%Y/%m", default="image/default.png", max_length=100,verbose_name='头像')
class Meta:
verbose_name = "用户信息"
verbose_name_plural = verbose_name
def __str__(self):
return self.username
Any friend can help?Thank you so much!
Obviously You can send file such as image to django via js, depending of what you have posted in your question, I am showing you a way that you can proceed, there are lots of other ways to accomplish this fairly.
Feel free to comment, if anything is not working.
$("#jsAvatarForm").submit(function(){
var form = this;
// var image = $("#avatarShow").val() You can not retrieve the image like this
var formData = new FormData($(form)[0]);
// Everything inside the html form is serialized in the formData
// No need to add X-CSRFToken, {% csrf_token %} is inside the form
formData.append("NEW_KEY","NEW_VALUE"); # In case of further values
$.ajax({
url:$(form).attr('action'),
type:$(form).attr('method'),
data:formData,
processData: false,
contentType: false, //Don't set any content type header
success: function(){
// all your stuffs here
$('#avatarShow').attr('src',data.avatar_url)
},
error:function(){
alert("error");
}
});
return false;
});
Django
from django.http import JsonResponse
# codes here
user_change.image = image
user_change.save()
return JsonResponse({'avatar_url':user_change.image.url})
Note: Show the post view that rendering this template.

AJAX gets access to Django HttpResponse variables

I am writing a small test app for a bigger project. I would like to use asynchronously FileReader() to read a txt file from client side and pass the textbody to the Django server by using AJAX. When the server succeeds to get the "posted" text, it will return the length of the text. It worked well on the server and I got what I expected. But now I would like to pass the size of the text(length) back to the client and display it somewhere on the web page asynchronously. But failed... Here is my code:
HTML
<script type="text/javascript">
var render_text = function(csvFile, onLoadCallback){
var reader = new FileReader();
reader.onload = onLoadCallback;
reader.readAsText(csvFile);
}
$(document).ready(function(){
$("#id_csvFileInput").on("change", function(e){
render_text(this.files[0], function(e){
var text = e.target.result;
$.ajax({
url: "",
type: 'POST',
async: true,
data: {'text': text},
success: function(data){
$("#id_test").text(data.size);
}
});
});
});
});
</script>
<p>
<input type="file" name="csvFileInput" id="id_csvFileInput" accept=".csv">
</p>
<div>
<p>Waiting for reponse context....</p>
<span id="id_test">?</span>
</div>
View.py
# Home page.
#csrf_exempt
def home(request):
template = 'hbvapp/home.html'
context = {}
if request.method == "POST" and request.is_ajax():
context['test'] = request.POST.get('text')
context['size'] = len(context['test'])
print context['size']
return render(request, template, context)
else:
return render(request, template)
ANY HELP WILL BE DEEPLY APPRECIATED !
Reagards
try it
from django.http import JsonResponse
if request.method == "POST" and request.is_ajax():
context['test'] = request.POST.get('text')
context['size'] = len(context['test'])
print context['size']
return JsonResponse(context)
# ^^^^^
more details jsonresponse
you can send it this way also:
context['test'] = request.POST.get('text')
context['size'] = len(context['test'])
print context['size']
return HttpResponse(json.dumps(context), content_type='application/json')
and in you js you can access it like this:
success: function(data){
$("#id_test").text(data['size']);
}

forbidden 403 error in 'PUT' request Ajax in django rest framwork

I am using django-rest framework while sending put ajax request got error 403 forbidden.
user-details.html
<form action="{% url 'user-detail' pk=object.pk %}" id="use1">
{% csrf_token %}
{% for key,value in serializer.items %}
{{key}} <input value="{{value}}" type="text" class="form-control" /><br>
{% endfor %}
<button class="btn btn-warning edit_record" type="button" >Update</button>
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#deleteModal">Delete</button>
</form>
when I click on update button ajax will call and here I got formdata with hidden field csrftoken and also other parameters but after run this ajax i got 403 forbidden error however "DELETE" method working fine here.
As far as I know we get this error when csrftoken is missing but I have csrf_token in my form.
$(".edit_record").on("click",function() {
var url = document.location.pathname
form = $(this).closest("form")[0],
formData = new FormData(form);
$.ajax({
type:'PUT',
url: url,
data: formData,
success: function (data) {
},
headers: {'X_METHODOVERRIDE': 'PUT'},
});
});
I used ModelViewset in views.py
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserProfileSerializer
def update(self, request, *args, **kwargs):
import pdb;pdb.set_trace()
response = super(UserViewSet, self).update(request, *args, **kwargs)
success = True if response.status_code in [200,201] else False
return Response({'object':response.data, 'success':success})
def partial_update(self, request, *args, **kwargs):
import pdb;pdb.set_trace()
def destroy(self, request,*args, **kwargs):
response = super(UserViewSet, self).destroy(request, *args, **kwargs)
success = True if response.status_code == 204 else False
return Response({'data':success})
I think It is a Problem with Django Security and your Cookies. You need to configure your Middleware. Please take a look at this SO solution and this piece of Django Documentation.
What you could try is adding this to your Ajax Call and I would change the type to POST instead of PUT.
$.ajaxSetup({
data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
type: "POST",
.....
});
What worked for me is implementing this into my JS:
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie != '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) == (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
try this,
$.ajax({
type:"DELETE",
data:{},
url:"{{ category_update }}",
beforeSend:function(xhr){
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
success:function(data,textStatus){
location.replace(location.href);
},
error:function(XMLHttpRequest, textStatus, errorThrown){
document.write(XMLHttpRequest.responseText);
}
});
the point is :
beforeSend:function(xhr){
xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
},
Thank you all for helping me but I got the solution by debug the dispatch method.Here I found that form data is missing that means there is invalid formdata in request.
There is no issue of csrf_token but issue in parameters which sent to ajax request.
In ajax currently i used -
form = $(this).closest("form")[0],
formData = new FormData(form);
and send this formData in request( still now i Don't know why it is not working here while i always used this thing in django).I just replace the above code with following code.
form = $(this).closest("form"),
formData = form.serialize()

Signing in through AJAX post request on Django All-auth

According to the documentation of django all-auth , it supports logging in through AJAX requests.When I make a normal post request to "accounts/login/" ,content type of the response header is "text/html".
But when I make a ajax call it is "application/json".
I am unable to figure what I am doing wrong, I have tried changing the contentType and dataType in ajax call but it gives a 400 Bad request error.
I have not modified any URL or view of the default Django all-auth app.
I am including the JavaScript code here -
<script type="text/javascript">
var $button = $('#login_button');
$button.on('click',function(){
var data = {"csrfmiddlewaretoken" : document.getElementsByName('csrfmiddlewaretoken')[0].value,
"login": $('#id_login').val(),
"password": $('#id_password').val(),
"remember": $('#id_remember').val() };
var temp = {'X-CSRFToken': document.getElementsByName('csrfmiddlewaretoken'[0].value };
$.post({
url : "{% url 'account_login' %}",
headers: temp,
type: "POST",
data : data,
contentType: "application/x-www-form-urlencoded",
dataType: "text",
success : function(data) {
// console.log(data);
},
});
});
</script>
it works for me, try:
$.post("{% url 'account_login' %}", {
"csrfmiddlewaretoken" : document.getElementsByName('csrfmiddlewaretoken')[0].value,
"login": $('#id_login').val(),
"password": $('#id_password').val(),
"remember": $('#id_remember').val()
},
function (data, status) {
// console.log(data);
});
I had similar issue and for me worked this solution (not a nice way but worked):
- in adapter.py you can see if form is not valid, status 400 and i have also changed the data
def ajax_response(self, request, response, redirect_to=None, form=None):
data = {}
status = response.status_code
if redirect_to:
status = 200
data['location'] = redirect_to
if form:
if form.is_valid():
status = 200
else:
status = 200
data['form_errors'] = form._errors
if hasattr(response, 'render'):
response.render()
data = response.content
return HttpResponse(json.dumps(data),
status=status,
content_type='application/json')
Here is how I used AJAX with vanilla JavaScript to login to django-allauth.
The django-allauth AJAX response does not include form errors, so I created a new class-based view based on Adam Starrh's solution:
from django.http import JsonResponse
from allauth.account.views import LoginView
class AjaxLoginView(LoginView):
def post(self, request, *args, **kwargs):
form_class = self.get_form_class()
form = self.get_form(form_class)
if form.is_valid():
response = self.form_valid(form)
return JsonResponse({'loggedIn': True})
else:
return JsonResponse({'loggedIn': False, 'errors': form.errors})
In urls.py I added a path to this view:
path('login-with-ajax/', AjaxLoginView.as_view(), name='loginWithAjax')
The function that makes the AJAX request does the following:
Create a new form with FormData() and add the login and password.
Encode the form with a helper method.
Use XMLHttpRequest() to post the form, using content type "application/x-www-form-urlencoded".
Here is the method I used:
loginWithAjax(submittedEmail,submittedPassword){
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest()
let form = new FormData()
form.set('login', submittedEmail)
form.set('password', submittedPassword)
xhr.open('POST', '/accounts/login-with-ajax/')
xhr.setRequestHeader('Content-Type', "application/x-www-form-urlencoded")
xhr.setRequestHeader("X-CSRFToken", this.getCookie("csrftoken"))
xhr.onload = () => {
if (xhr.status === 200) { //received an ajax response from view
let ajaxResponse = {
loggedIn: false,
error: ''
}
let viewResponse = JSON.parse(xhr.response)
ajaxResponse.loggedIn = viewResponse.loggedIn
if (!ajaxResponse.loggedIn){
ajaxResponse.error = viewResponse.errors.__all__[0]
}
resolve(ajaxResponse)
} else { //did not receive an ajax response from view
reject(xhr.status)
}
}
xhr.send(this.urlencodeFormData(form))
})
}
I used the method provided by cuixiping to encode the form:
urlencodeFormData(fd){
var s = '';
function encode(s){ return encodeURIComponent(s).replace(/%20/g,'+'); }
for(var pair of fd.entries()){
if(typeof pair[1]=='string'){
s += (s?'&':'') + encode(pair[0])+'='+encode(pair[1]);
}
}
return s;
}
I hope this saves someone some time in the future.

How to make an ajax request to a view

I am trying to figure out how I can make an ajax request (with jquery) from my template in order to execute a view on a button click. I don't want to redirect to another page. I just need to execute the code in the view.
This is my on button click event:
$(document.body).on("click", "#download_xls",function(e) {
selected_country = ($("#button-countries").val())
selected_subareas = $('#_all_values').val();
id = "?country=" + selected_country + "&" + "regions=" + selected_subareas
whole_url = "{% url 'test_download' %}" + id
$("#download_xls").attr("href", whole_url)
});
As I pass the values in my URL, I don't even need to pass some parameters through the ajax request. I just need to execute the code in the view.
The view is something like this:
def test_download(request):
print(request.GET.get('country'))
print(request.GET.get('regions'))
fileContent = "Your name is %s"
res = HttpResponse(fileContent)
res['Content-Disposition'] = 'attachment; filename=yourname.txt'
return res
EDITED
I have added the ajax GET request in my template as:
whole_url = "{% url 'test_download' %}"+id
$.ajax({
type: "GET",
url: whole_url,
success: function(data) {
alert('sd')
},
error: function(data) {
alert('error')
},
});
I get an error cause there is no corresponding template for this view. I think I need to add something in the urls.py file.
I read here that I need to modify urls.py as:
url(r'^link-to-fun1$', views.fun1),
But its not clear to me what should be the link-to-fun1.
I tried:
url(r'^create$', 'test_download', name='test_downlad'),
But gives an error: No Reverse Match.
You could use TemplateView add to your url and use JQuery to do something, like this:
views.py
class ajax_view(TemplateView):
def get(self, request, *args, **kwargs):
id_value = request.GET['id']
value = Model.objects.filter(id=id)
data = serializers.serialize('json', value, fields=('fieldone'))
return HttpResponse(data, content_type='application/json')
urls.py
url(r'^ajax/$', ajax_view.as_view()),
JQuery
$.ajax({
data: { 'id': id },
url: '/ajax/',
type: 'get',
success: function (data) {
// Do something with the data
}
})
That's in general how you can use Ajax with Django, the important is the use of TemplateView

Resources