Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
I have little code over here.
Can you please explain me that what that code exactly does in details. please.
In script here is the ajax call:
$.ajax({
url : "{% url 'upload_document' %}",
type: "POST",
data : {csrfmiddlewaretoken: document.getElementsByName('csrfmiddlewaretoken')[0].value,
title: document.getElementById('title').value,
//document: document: document.getElementById('document'),
},
dataType : "json",
success: function( response ){
if(response == "True"){
// success
}
else {
//append errors
}
}
});
How ajax is works in django and how can we use ajax request in view.
Here my views
views.py
def upload_document(request):
print request.POST
print request.FILES
if request.is_ajax():
if request.method == 'POST':
form = UploadForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
form.save()
return HttpResponse(simplejson.dumps('True'), mimetype = 'application/json' )
else:
errors = form.errors
return HttpResponse(simplejson.dumps(errors), mimetype = 'application/json' )
Thanks in Advance.
In general, $.ajax method sends an asynchronous http request.
You can read about it here.
First argument is url, where we send request.
Second, is request method it may be GET, POST, PUT, DELETE and etc. see wiki
Third argument is key-value dictionary with data, which you use in server-side.
In django, you may access it in request.POST(in case of post request)
Fourth argument is function, which is invoked when server succesfully returns response.
You do not need if statement in this function, because when request fails or server does not give a response, or server returns error(something like 40* code for example) this function will not be invoked.
This function takes one argument with server's response. You need handling this data, for example showing user a message like Invalid data, please correct errors... or Valid data. your request is in process now. and staff like that.
Last argument is data type of servers response. jQuery is smart enough to parse json or html for you, so in this case, response(argument of success function) is pure JS object, deserialized from JSON.
In your server-side(Django views) you must do some validation of request's data. and do something with it. For example, save it to database. When i have to implement ajax form processing i do sumething like this:
if request.method == 'POST':
response = {}
form = UploadForm(request.POST, request.FILES, user = request.user)
if form.is_valid():
form.save()
response['success'] = 1
else:
response['success'] = 0
response['errors'] = dict(form.errors)
return HttpResponse(simplejson.dumps(response), mimetype = 'application/json' )
And on client side, in js something like this
$.post('/url/to/view',
function(json){
if(json['success']){
alert('Yahooo! Successfull request')
}
else{
alert('Oooops. Looks like you send invalid data')
}
}, 'json')
Good luck!
Related
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
Is it possible to create function without template?
Like I'm trying to create delete function and what I want to do is to delete something immediately after clicking the delete button and then redirect to other page.
I want to place a delete button on the page users can edit their post.
html is like this
<button type="submit" class="btn btn-outline-secondary">Save Changes</button>
</form>
and I want to place delete button next to this button.
def edit_entry(request, entry_id):
'''Edit a post.'''
entry = Entry.objects.get(id=entry_id)
if request.method != 'POST':
form = EditEntryForm(instance=entry)
else:
form = EditEntryForm(instance=entry, data=request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse_lazy('main:index'))
return render(request, 'main/edit_entry.html', {'entry': entry, 'form': form})
def delete_entry(request, entry_id):
'''Delete post'''
#I don't wanna create template for this function.
pass
Anyone who can give me tips?
by the docs simple-view you can use the httpresponse
from django.http import HttpResponse
def delete_entry(request, entry_id):
'''Delete post'''
#I don't wanna create template for this function.
return HttpResponse('done')
Usually it make sense to use ajax for this purpose.
In this case the handling of click splits into steps:
1) You click the button
2) jQuery (or any other javascript code) catches click event and sends AJAX request (usually post request, because post is used to for data modifications in REST agreement) to defined url on your server (like /delete/my/some/thing/) in urls.py
3) Djnago routes request to the delete_something view (or function)
4) delete_something takes request, checks what you want to check (like some permissions of current user), deletes what you actually want to delete and makes ajax response.
5) jQuery takes this response (which it actually waits on 3-4 steps) and checks response content to detect if server says everything is ok or there is some error.
So this is the code to create ajax request from jQuery:
$('#delete-button').click(function(){
var delete_id = (#delete-button).data()
$.ajax
({
url: '/delete/my/some/thing/',
data: {"id": delete_id},
type: 'post',
success: function(result)
{
// here you can write code to show some success messages
},
error: function(result) {
// here you can write code to show some error messages or re-send request
}
});
});
You also can use not $.ajax() method, but $.post(), if you want.
This is the code from this answer to make Django json response:
return HttpResponse(json.dumps(response_data), content_type="application/json")
It could look like this:
import json
from django.http import HttpResponse
def delete_something(request):
resp_data = {}
user = request.user
delete_id = request.POST.get('delete_id') # or None, if there is no delete_id
# here you can check user permissions, if your site has them
# for example check that user can delete something and can delete this entity by writing check_user_can_delete() function
if delete_id and check_user_can_delete(user):
# do your deletion
resp_data = {'status': 'ok'}
else:
resp_data.update(errors=[])
if no delete_id:
resp_data['errors'] = 'no delete_id'
if not check_user_can_delete(user):
resp_data['errors'] = 'you cave no permissions to delete delete_id'
resp = json.dumps(resp_data)
return HttpResponse(resp, content_type='application/json')
Also note that Django 1.7 has JsonResponse object, as shown in SO answer I mentioned.
I use the $.ajax to request the data, but how can I let the page switch as the same time?
in my js:
$.ajax({
type:'post',
url:'/api/server_payment',
...
success:success_func,
})
function success_func(response){
...
}
In my views.py:
def server_payment(request):
if request.method == 'POST':
# I don't know what to write here, because there I will switch the web page, and then fill the request data to the switched template.
EDIT
Because I want to pass data by the ajax to the views.py , and in the views.py I want to switch the url to a new url, and in the new url , I will render the passed data.
Because use the ajax requert I will get the response in the ajax callback function.
You just pass your data from ajax to the views with the post data:
file.js
data = {
'key': value,
'another_key': another_value,
// as many as you need
...
}
$.ajax({
type:'post',
url:'/api/server_payment',
data: data
...
success:success_func,
})
function success_func(response){
...
}
Now in your view server_payment store them in the session :
def server_payment(request):
if request.method == 'POST':
request.session['key'] = request.POST.get('key')
request.session['another_key'] = request.POST.get('another_key')
...
return HttpRedirectResponse('/other/url')
And now in your other views (corresponding to the one at '/other/url', you'll access to the data in request.session. In the other views, get data by poping them to empty the request.session dict :
views.py rendering the data
def another_view(request):
data = {}
data['key'] = request.session.pop('key', "NOT_FOUND") # this will prevent from raising exception
data['another_key'] = request.session.pop('another_key', "NOT_FOUND")
...
return render('/your/template.html', data)
I want to pass data by the ajax to the views.py , and in the views.py I want to switch the url to a new url, and in the new url , I will render the passed data.
The thing I don't understand is why you don't send your post data directly in the good view to render instead of having a view getting the post data and redirecting to another one.
I have an ajax call that sends a country label to my view function below:
views
...
posts = Post.objects.all()
if request.method == 'POST':
country = request.POST.get('country')
print('COUNTRY:', country) #successfully prints
posts = Post.objects.filter(country=country)
context = {
...
'posts': posts,
}
return render(request, 'boxes.html', context)
I successfully get the ajax data but what do I do after this in order to redirect to the same view with the new posts value?
If you are using Ajax.You have to use window.location.reload(); in success method of Ajax post call.
As i read that you are using Ajax:
The function reload #Himanshu dua said is ok
And i should check the way you use URL and VIEW
# The function reload will work well if you change the DATA
# and it will reload and return again the New value from data
Or you should try to replace the old with the new DATA you got from Server via ajax (just change the value with Jquery)
In your example the view returns a rendered template: boxes.html. For this to work, you would have to either
modify your view to use query parameters (eg /my/url?country=nowhere). This would then work with GET requests instead of posts, and you can easily call it via URL.
or use a html form instead of AJAX requests. A form can easily POST to an endpoint and it will load whatever your webserver returns.
Ajax calls are designed to exchange data with a server, not really for downloading whole webpages. So if you wanted to use ajax, you could make your view return a json/xml/whatever list of objects and then use js inject them into your page:
function successCallback(data) {
var elem = document.getElementById('myelement');
elem.innerHTML = data;
}
It doesn't work that way.
On the HTML page, using Javascript, you should:
(1) Send an AJAX call (GET/POST) to load the view function in the
backend
(5) Receive the output of the view function and do whatever you want with it.
On the Backend, using the view function, you should:
(2) Receive the GET/POST Data from the frontend (HTML)
(3) Do whatever you want with that.
(4) Return the output of the function as JSON using HttpResponse
Note the numbers next to each item. It happens according to that
sequence from 1 to 5.
Here is an example:
On the HTML Page (Javascript):
var posts;
$("button").click(function(){
$.post("/test/", function(data, status){
posts = data;
console.log(data);
});
});
On the Backend (Python):
import json
from django.http import HttpResponse
def test(request):
if request.method == 'POST':
country = request.POST.get('country')
posts = Post.objects.filter(country=country)
return HttpResponse( json.dumps(posts) )
else:
return HttpResponse( "error" )
I'm trying to make a contact form with python django, at this time it works perfectly, the issue is that I have to wait up to the email message already sends to get the Httpresponse.
Is there any way to return the Httpresponse first and then send the email message?
send_mail(
'Subject here',
data['comentarios'],
'myemail#gmail.com',
['myemail#gmail.com'],
fail_silently=False,
)
return HttpResponse('bien') #es menor a 7 digitos
I assume you want to let the user see that the email has been sent/the request has been processed immediately after clicking 'Send'. I suggest that you use AJAX to achieve what you are doing.
Thought Process
One thing to note is that you probably want to show a loading gif/svg or something to indicate that the email is in the process of being sent. While the loading gif is shown, proceed with form validation:
if everything is ok: proceed with AJAX request send email and return a success/error message indicating whether email was sent.
if validation failed: just display error messages
However, if you want to display a message, like 'Thank you', it's something like this:
It should probably look something like this in your JS (if you're using jQuery):
$('#form').on('submit', function(e) {
e.preventDefault();
// do some validation
// if the validation deems the form to be OK - display the 'Thank you!` message first THEN proceed to AJAX request.
$('#form').append('Thank you!');
// insert AJAX here
...
// if the validation returns errors - just display errors
...
});
The actual AJAX request:
// AJAX request
$.ajax({
method: 'POST',
url: '../send_email/', # Just an example - this should be a url that handles a POST request and sends an email as a response
data: $('#form').serialize(),
success: function(response) {
// anything you want
// an example would be:
if (response.success) {
$('#form').append(response.success);
}
});
In your views.py:
class SendEmail(View):
def post(self, request, *args, **kwargs):
if request.is_ajax():
send_mail(
'Subject here',
data['comentarios'],
'myemail#gmail.com',
['myemail#gmail.com'],
fail_silently=False,
)
return JsonResponse({'success': 'Just a JSON response to show things went ok.'})
return JsonResponse({'error': 'Oops, invalid request.'})