Using Delete request in Django outside of a form - ajax

I am trying to create a simple todo list app that uses POST to post data into the data base and a 'x' (\u00D7) to delete the todo. The code is as following:
Views.py
def delete(self, request, id):
print(request.DELETE)
self.model.objects.get(pk=request.delete['pk']).delete()
return render(request, self.template_name, {'object_list':self.model.objects.all()})
Models.py
class TodoDB(models.Model):
todos = models.CharField(max_length=1000)
day = models.CharField(max_length=10)
def __str__(self):
return str(self.todos)
HTML and JS
<ul class="list-group list-group-flush" id="list-group">
{%for item in object_list%}
<li class="list-group-item">{{item.todos}}</li>
{%endfor%}
</ul>
for (var i = 0; i < close.length; i++) {
close[i].onclick = function() {
var li = this.parentElement;
li.style.display = "none";
$.ajax({
type: 'DELETE',
url: "{%url 'todo_list'%}",
data:{'pk':pk},
success: function(data){
alert("Success!");
},
error: function(){
alert("Error! Couldn't send delete request")
}
});
}
Any help would be great. Thanks!
EDIT: I forgot to add the error: The error was csrf_token not found. I put the entire list under a new form tag and inserted a {%csrf_token%} in there, but it still doesn't accept the token.

Please consider reading
https://docs.djangoproject.com/en/2.0/ref/csrf/
on how it is made up in Django.
In brief you would need to render csrf token in your form and post it with AJAX during your request.
Your error is just about that.
data:{'pk':pk},
In your JS part should look something like:
data:{
'pk':pk,
'csrf_token': [your rendered token here...]
},

Related

Converting formData to forms.Form in django

I would like to allow user to key in a quiz code and gets an alert to tell whether if the code is still invalid without refreshing the page. I already read a lot of Django AJAX and JQuery tutorials but most of them seem outdated because they do not cover the part where csrf token must be send.
In my settings.py, I set CSRF_USE_SESSIONS to True.
This is my forms.py
class codeForm(forms.Form):
code = forms.IntegerField(label='Question Code')
In my html file, I have this
<form class="card__form" id="code-form" method="POST">
{% csrf_token %} <script type="text/javascript"> // using jQuery
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); </script> {{form.as_p}
<center><input type="submit" class="btn btn-primary card__submit" id="submit_code"></center>
Just before the tag, I have this :
<script>
$(document).ready(function(){
$("#submit_code").click(function(){
alert("Text: ");
event.preventDefault();
var myform = document.getElementById("code-form");
var form = new FormData(this);
form.append('csrfmiddlewaretoken', csrftoken);
$.ajax({
data : form,
dataType:'json',
type: 'POST',
method: 'POST',
url: '{% url 'student:process_code' %}',
contentType: false,
processData: false,
success: function(context) {
alert(context.msg);
},
error: function(context) {
alert(context.msg);
}
});
});
});
</script>
In my views.py
def process_code(request):
context = {}
if request.method == 'POST':
form = codeForm(request.POST)
if form.is_valid():
cd = form.cleaned_data
code = cd.get('code')
print('yay')
if code.isdigit():
The unexpected result was the form is not valid (form.is_valid() = false). Thus, I think my formData object is not converted to a valid forms.Form type.
I also tried to use form = codeForm(request.POST['code']) but it return more error.
How can I get around this? I prefer not to use serialize() because I read that it cannot be used for uploading files which will be my next feature to work on after this has settled. I wanted to use forms.Form because it has cleaned_data method. If you could provide a good solution although not using forms.Form but with good reasoning, I will appreciate it. Thank you so much
try FormData(myform), not "this"

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']);
}

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

Using Ajax call to update a Django view

I am new to Django, and am stuck attempting to get a variable sent from ajax to be used in the Django view. My view:
def index(request):
if (request.is_ajax()):
username = request.GET['user']
else:
username = ''
context = {'user':username}
return render(request, 'index.html', context)
and the ajax:
$.ajax({
url: '/index/',
type: 'GET',
data: {user: response.name, page: page}
});
My issue is that username does not update in the view, based on the ajax call. I know the ajax call is working properly, because upon looking at the network response it is passing the proper updated username.
What I believe is happening is that the view is loaded, then the ajax call occurs and updates username, but the view is not re-rendered and thus won't change. I have tried putting another render after getting the username, but that did not change anything, and I have also made a separate view for handling the ajax call, but that doesn't seem to work either, since the view always loads without ajax request being true.
What is the way to get this working? Thanks for any help.
If you intend to return a response via Ajax that JavaScript can then use to update your DOM, you need to return an HttpResponse, preferably in JSON format, which can be passed to a handler in your $.ajax call. Example:
import json
from django.contrib.auth.models import User
from django.http import HttpResponse
from django.shortcuts import render
def index(request):
if request.is_ajax():
username = request.GET.get('user', '')
user = User.objects.get(username=username)
# do whatever processing you need
# user.some_property = whatever
# send back whatever properties you have updated
json_response = {'user': {'some_property': user.some_property}}
return HttpResponse(json.dumps(json_response),
content_type='application/json')
return render(request, 'index.html', {'user': ''})
Then in your JavaScript, you can do:
$.get('/index/', {user: response.name, page: page}, function(json_response) {
console.log(json_response.user.some_property);
});
With this approach, a normal GET request to your view returns a rendered HTML template. For an Ajax request, the view returns an HttpResponse in JSON format that gets passed to the callback in the jQuery $.get call.
To send data to django view via Ajax call, you need to add data to Form and then send in ajax request.
Example:
My view.py :
def index(request):
"""
View function to handle Ajax request for image Link.
:param request: Ajax request data.
:return: image URL.
"""
if request.is_ajax():
try:
username = request.POST['username']
# perform operations on the user name.
except:
e = sys.exc_info()
return HttpResponse(e)
return HttpResponse(sucess)
else:
raise Http404
My template index.html
<html>
<head>
<title>Index</title>
<script>
$(document).ready(function() {
$('#btnSubmit').click(function() {
var data = new FormData();
var username = $('#id_username').val()
data.append('username', username);
$.ajax({
type: 'POST',
url: 'getuser/',
data: data,
processData: false,
contentType: false,
success: function(json) {
alert(json);
}
})
});
});
</script>
</head>
<body>
<h1>Index</h1>
User name: <input type="text" name="fname" id="id_username">
<input type="submit" id ="btnSubmit" name="submit" value="Send Test Push">
</body>
</html>
After this you need to add ajax call url into urls.py.

Django Ajax-Jquery does not fetch the data

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.

Resources