Django Ajax-jQuery - ajax

Since I am relatively new to Ajax and jQuery, and having hard time doing this, I am posting this over here.
Views.py
if request.is_ajax():
if request.method == "POST":
chatroom_id = request.POST['chatroom_id']
else:
chatroom_id =''
print chatroom_id
When I remove if request.is_ajax() condition , then it shows the error saying Key 'chatroom_id' not found in <QueryDict: {u'reply': [u''], u'csrfmiddlewaretoken': [u'yIJct9O7WfyPnWmDosW9N5TEklRwoIHP']}>
Template.html
{% for key, values in chat_data.items %}
<div class="container-fluid" alt = {{key}}>
<div class="row-fluid">
<div class="span2">
{{values.from}} <br/> {{values.init_query}}
</div>
<div class="span10 well">
{% for k in values.chat %}
<label> Text : {{k.text}} </label>
<label> {{k.date_time}} </label>
{% endfor %}
<form action = "#" method = "POST" id = {{key}} class="chatroom">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value = "Sent" class="btn btn-primary">
</form>
</div>
</div>
</div>
{% endfor %}
Since, there will be many chats and correspondingly reply submit button and its key, I want that when I reply to a specific chat, it carries the key with itself and process the chat accordingly.
How can I achieve this using Django, jQuery and Ajax? Replies to be being sent should give via Ajax using jquery
I have written these jQuery lines of code, but they seem not to work. Where I am going wrog
<script type="text/javascript">
var form = $('#'+'{{key}}');
form.submit(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "/dashboard",
data : form.serialize(),
success: function( response ) {
console.log( response );
}
});
return false;
});

I believe that the best free resource on the matter is Mike Hibbert's video on using django with jquery to implement ajax.

For the jQuery, you have a few mistakes, the post should look like this:
var form = $('#'+'{{key}}');
form.submit(function (event) {
event.preventDefault();
$.ajax({
type: "POST",
url: "/dashboard",
data : form.serialize(),
success: function( response ) {
console.log( response );
}
});
return false;
});
Try that and tell me how it goes.

When you make an Ajax request with jQuery and Django with csrf you need to pass the token, this uses the jQuery cookie plugin from Django's docs https://raw.github.com/carhartl/jquery-cookie/v1.3.1/jquery.cookie.js :
/** Django's csrftoken ajax security & server failures */
App.ajax = (function () {
var csrftoken = $.cookie('csrftoken'),
host = document.location.host,
protocol = document.location.protocol,
sr_origin = '//' + host,
origin = protocol + sr_origin;
return {
'csrfSafeMethod': function (method) {
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
},
'sameOrigin': function (url) {
return (url === origin || url.slice(0, origin.length + 1) === origin + '/') || (url === sr_origin || url.slice(0, sr_origin.length + 1) === sr_origin + '/') || !(/^(\/\/|http:|https:).*/.test(url));
},
'$setup': function () {
var scope = this;
// TODO: create server failure pages and alert mechanism
$.ajaxSetup({
statusCode: {
401: function () {
},
403: function () {
}
},
beforeSend: function (xhr, settings) {
if (!(scope.csrfSafeMethod(settings.type) && scope.sameOrigin(settings.url))) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
return this;
}
}());
$(document).ready(function(){
App.ajax.$setup()
var $form = $('form');
$form.on('submit' function(e){
e.preventDefault();
$.ajax({
type: "POST",
url: '/dashboard',
data: $form.serialize(),
success: function (response) {
window.alert(response);
}
});
});
});
Personally I would prefer to pass JSON, also what browser are you testing in? Look into these libraries:
https://raw.github.com/marioizquierdo/jquery.serializeJSON/1.0.0/jquery.serializeJSON.js
https://raw.github.com/MoonScript/jQuery-ajaxTransport-XDomainRequest/master/jQuery.XDomainRequest.js

Related

Redirect to a specific page in Laravel using ajax

I have created ajax function when the user clicks the button, it will check first the users profile if account is already confirmed. If not, it will redirect back to user dashboard. However, my problem now is that the page is not displayed or it is not redirecting back. The result can only be seen in the browsers' network tab.
my ajax
$(document).on("click", "#apply", function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "get",
url: '/checkstatus',
success: function(store){
if(store == 'confirmed'){
$(".apply_modal").toggleClass("open").show();
$("body").toggleClass("open");
}
},
});
});
and my controller:
public function checkStatus(Request $request)
{
$verify = Auth::user()->verifyAccount();
if($verify == false){
if(session()->has('verify') && session()->get('verify') != '') {
session()->forget('verify');
} else {
session()->flash('verify', 'At first, please update your profile!');
}
}else{
return 'confirmed';
}
}
How can I properly redirect back the user to its main page? The result for now is like this.
Message to the user :
#if(session('verify'))
<div class="complete_box">
<p>{{ session('verify') }}</p>
Close
</div>
#endif
you can not redirect through controller if you are using ajax. you need to use javascript
window.location.href = "your url";
window.location.href = "{{url('/mypage')}}";
$(document).on("click", "#apply", function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "get",
url: '/checkstatus',
success: function(store){
if(store == 'confirmed'){
$(".apply_modal").toggleClass("open").show();
$("body").toggleClass("open");
window.location.href = "your url";
}
},
});
});
for flash message use session
public function checkStatus(Request $request)
{
$verify = Auth::user()->verifyAccount();
if($verify == false){
\Session::put('message','At first, please update your profile!');
return 'something you want';
}else{
return 'confirmed';
}
}
Now in blade file where you want to show flash put this
#if(Session::has('message'))
<p class="alert alert-success">
{!! Session::get('message') !!}
×
</p>
#endif
$(document).on("click", "#apply", function(){
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$.ajax({
type: "get",
url: '/checkstatus',
success: function(store){
if(store == 'confirmed'){
$(".apply_modal").toggleClass("open").show();
$("body").toggleClass("open");
window.location.href = "store.url";
}
},
});
});
Here the store.url is that url which is coming in response.
In controller
Craete a url and send in response.

Issue with ajax call csfr token

I am trying to add an ajax call that changes the status of a listing, between listed and unlisted, when submitting the form I am having a 403 forbidden error in the console of the browser, I made some checking and it appears that Django is forbidding the form because of a lack of csrf token, however I am not good in javascript, so any help would be appreciated.
Here is my code in my view:
#require_POST
#ajax_required
#login_required
def unlist_ajax(request):
pk = request.POST.get('pk', None)
is_visible = request.POST.get('is_visible', None)
if pk and is_visible:
listing = get_object_or_404(Listing, pk=pk)
if is_visible == 'true':
listing.is_visible = False
listing.save()
messages.success(request, _("Listing unlisted"))
return JsonResponse({'status': 'ok'})
else:
listing.is_visible = True
listing.save()
messages.success(request, _("Listing re-listed"))
return JsonResponse({'status':'ok'})
and here is the template script:
in the top of the template, in the header:
<script>
function unlistPostAjax(listing_id, is_visible) {
var confirmation = confirm("{% trans 'are you sure you want to change the status of your listing?' %}");
if (confirmation) {
$.post("{% url 'dashboard:unlist_ajax' %}", {pk: listing_id, is_visible: is_visible}, function (response) {
console.log('sending delete query'); location.reload();
})
}
}
</script>
and in the bottom of the body:
<script src="{% static 'js/jquery.cookie.js' %}"> </script>
<script>
$(document).ready(function () {
var csrftoken = $.cookie('csrftoken');
function csrfSafeMethod (method) {
// These HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function (xhr, settings) {
if(!csrfSafeMethod(settings.type) && !this.crossDomain) {
// Set X-CSRFToken HTTP Header
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
});
</script>
You can add this to the top of your <script> or if you have a base html template you can put this in there too.
{% csrf_token %}
<script type="text/javascript">
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
});
</script>
Believe you just need to add the csrf above the script you defined, but this is the whole implementation I currently use. I have no issues.

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.

Django Ajax Form submit wrongly redirect to another page

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)

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

Resources