I have a problem,Django my ajax post is not working. when i look at the console quantity is not undefined. But my request.post is not working.
<form method="POST">
{% csrf_token %}
<ul>
<li>
<div class="form-group quantity-box">
<label class="control-label">Quantity</label>
<input
class="form-control"
id="quantity"
value="0"
min="0"
max="20"
type="number"
/>
</div>
</li>
</ul>
<div class="price-box-bar">
<div class="cart-and-bay-btn">
<a class="btn hvr-hover" data-fancybox-close="" href="#"
>Buy New</a>
<button type = "submit">
<a class="btn hvr-hover" data-fancybox-close="" id= "qtyButton" data-fancybox-close="" href="{% url 'addCart' %}">Add to cart</a>
</button>
</form>
my js script
$('#qtyButton').click(function(e){
e.preventDefault();
var qty = $('#quantity').val();
var id = {{product.id}};
$.ajax({
type: "POST",
url: "{% url 'addCart' %}",
dataType: 'json',
data: {
"quantity":qty,
"product_id":{{product.id}},
}
});
});
my view.py file
def addCart(request):
if request.method == 'POST':
post = request.POST
quantity = post.get('quantity')
id = post.get('product_id')
item = Product.objects.get(id=id)
Cart.objects.get_or_create(user_id=request.user, product_id=item, quantity=quantity)
else:
return render(request, 'cart.html')
return redirect(request.META.get("HTTP_REFERER", "/"))
I tried so many things. But none of them is working. What should i do ?
You need to pass Jsonresponse() response instead of render() response like this
views.py
from django.http import JsonResponse
def CreditSaveView(request):
if request.method == 'POST':
creditform = CreditForm(request.POST)
if creditform.is_valid():
amt = request.POST['amt']
tag = request.POST['tag']
crs = request.POST['csrfmiddlewaretoken']
CreditModel(amt=amt,tag=tag).save()
return JsonResponse({'status':'done'}
script
<script>
document.getElementById("creditbtn").addEventListener("click", function () {
let id_amt = document.getElementById('id_amt').value;
let id_tag = document.getElementById('id_tag').value;
let crs = document.getElementsByName('csrfmiddlewaretoken')[0].value
my_data = { csrfmiddlewaretoken: crs, amt: id_amt, tag: id_tag };
console.log(my_data)
$.ajax({
url: "/creditsave/",
method: "POST",
data: my_data,
// dataType: "json",
success: function (data) {
if (data.status == 'done') {
// document.getElementById('creditform').reset()
console.log(data)
document.getElementsByTagName('form')[1].reset()
}
}
});
});
</script>
Related
i check with django document and But my problem was not solved
[08/Feb/2023 15:57:18] "POST /courses/2/learning-django HTTP/1.1" 403 2506
error:
Forbidden (CSRF token missing.): /courses/2/learning-django
this is my models
class Review(models.Model):
course = models.ForeignKey(Product, on_delete=models.CASCADE, related_name='reviews')
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
rating = models.IntegerField(null=True, validators=[MinValueValidator(1), MaxValueValidator(5)])
comment = models.TextField()
created = models.DateField(auto_now_add=True)
active = models.BooleanField(default=False)
def __str__(self):
return f'{self.first_name} {self.last_name}
my views:
def productDetailView(request, id, slug):
product = get_object_or_404(Product, id=id, slug=slug, available=True)
new_comment = None
if request.method == 'POST':
form = ReviewForm(request.POST)
if form.is_valid():
new_comment = form.save(commit=False)
new_comment.course = product
new_comment.rating = request.POST['rating']
new_comment.save()
else:
form = ReviewForm()
return render(request, 'shop/product_detail.html', {'product': product, 'form': form})
js function:
$(document).ready(function(){
$('.rate .rate-item').on('click', function(){
var value = $(this).data('value');
$.ajax({
url: '{{ product.get_absolute_url }}',
type: 'POST',
data: {'rating': value},
success: function(response){
alert('Rating saved successfully!');
}
});
});
});
my template
<form method="post">
<div class="row">
<div class="col-md-6">
<div class="form-singel">
{{ form.first_name|attr:" placeholder:Fast name" }}
</div>
</div>
<div class="col-md-6">
<div class="form-singel">
{{ form.first_name|attr:" placeholder:Last Name"}}
</div>
</div>
<div class="col-lg-12">
<div class="form-singel">
<div class="rate-wrapper">
<div class="rate-label">Your Rating:</div>
<div class="rate">
<div data-value="1" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="2" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="3" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="4" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
<div data-value="5" class="rate-item"><i class="fa fa-star" aria-hidden="true"></i></div>
</div>
</div>
</div>
</div>
<div class="col-lg-12">
<div class="form-singel">
{{ form.first_name|attr:" placeholder:Comment" }}
</div>
</div>
{% csrf_token %}
<div class="col-lg-12">
<div class="form-singel">
<button type="submit" class="main-btn">Post Comment</button>
</div>
</div>
</div> <!-- row -->
</form>
I used csrf_token in my form but it seems that dosen't work
and i searched in stackoverflow no one have same error
how do i fix it
If you want to make AJAX request, you need to add CSRF token to the data body.
$.ajax({
url: '{{ product.get_absolute_url }}',
type: 'POST',
data: {'rating': value, csrfmiddlewaretoken: '{{ csrf_token }}'},
success: function(response){
alert('Rating saved successfully!');
}
});
Original answer: https://stackoverflow.com/a/6170377/5711733
Basically what you miss is csrftoken in the form data.
You have two possibilities:
Either define view with #csrf_exempt:
from django.views.decorators.csrf import csrf_exempt
#csrf_exempt
def productDetailView(request, id, slug):
product = get_object_or_404(Product, id=id, slug=slug, available=True)
new_comment = None
Or load variable from cookie and pass it into headers (I'm using js-cookie library but you can find single functions on stack overflow that will fit your needs) - example:
$.ajax({
url: url,
type: 'POST',
headers: {
'X-CSRFTOKEN': Cookies.get('csrftoken'),
},
success: (data) => {
location.reload();
}
})
From what I know first solution should be more secure.
In the castmascotvote view, everything is working when I'm authenticated, but not working otherwise. I have a print('entering not authenticated') right when it enters the else statement if the user isn't authenticated, but it never enters it, i'm boggled. I don't understand at all why it's not working. does anyone have any idea where I should start looking?
error message
The view didn't return an HttpResponse object. It returned None instead.
But I clearly have a HttpResponse object!
.html
<form class="mascotvoteform" action="{% url 'castmascotvote' mascot.id %}" id="{{mascot.id}}">
<div class="p-0"><h4>{{ mascot.name }} </h4> <p> by {{ mascot.author }} </p></div>
<div class="p-0"><img class="img-thumbnail" src="{{ mascot.image.url }}" style="width:250px;"></div>
<div class="row p-3">
{% if mascot.total_votes is 0 %}
<div class="col"><h5 id="mascotvotes{{mascot.id}}">0</h5></div>
<button class="col btn btn-primary" type="submit" id="castmascotvote{{mascot.id}}">Vote</button>
{% else %}
<div class="p-0 col"><h5 id="mascotvotes{{mascot.id}}">{{ mascot.total_votes }}</h5></div>
<button class="col btn btn-primary" type="submit" id="castmascotvote{{mascot.id}}">Vote</button>
{% endif %}
</div>
</form>
.script
$( document ).ready(function() {
$(".mascotvoteform").submit(function(e) {
{% if user.is_authenticated %}
e.preventDefault()
{% endif %}
let mascot_id = $(this).attr("id");
let url = $(this).attr('action');
$.ajax({
type: 'POST',
url: url,
data: {
'csrfmiddlewaretoken': $('input[name=csrfmiddlewaretoken]').val(),
'mascot_id': mascot_id,
},
success: function(response) {
console.log('success', response)
$(`#mascotvotes${mascot_id}`).text(`${response['total_votes']}`)
};
},
error: function(response) {
console.log('error', response)
}
});
})
.views
def castmascotvote(request, mascot_id):
mascot = PoopMascot.objects.get(id=mascot_id)
user = request.user
if request.method == 'POST':
if user.is_authenticated:
if user in mascot.votes.all():
mascot.votes.remove(user)
else:
mascot.votes.add(user)
total_votes = mascot.total_votes()
data = { "total_votes":total_votes }
return JsonResponse(data, safe=False)
else:
print('entering user not authenticated')
messages.error(request, 'Please sign in to vote Poop Hero!')
return render(HttpResponseRedirect(reverse('user_login')))
else:
pass
I am trying to implement a search function to search for users of my blog. In my base.html I have my navbar and within the navbar I have the following search form:
<form class="form-inline" method="POST">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">#</span>
</div>
{% csrf_token %}
<input id="user_search" type="text" class="form-control" placeholder="Username" aria-label="Username" aria-describedby="basic-addon1">
<ul class="list-group" id="results"></ul>
</div>
</form>
My ajax code looks as follows:
$('#user_search').keyup(function(){
$.ajax({
type: 'POST',
url: "{% url 'user-search' %}",
data: $(this).serialize(),
dataType: 'json',
success: function(response){
$('#results').html(response['form']);
console.log($('.profile-section').html(response['form']));
},
error: function(rs, e){
console.log(rs.responseText);
},
});
});
and my views.py search view looks as follows:
def user_search(request):
if request.method == 'POST':
search_text = request.POST['search_text']
else:
search_text = ''
users = User.objects.filter(username__icontains=search_text)
context = {
'users': users,
}
if request.is_ajax():
html = render_to_string('feed/user_search.html', context, request=request)
return JsonResponse({'form': html})
and the relevant part of my urls.py looks like this:
path('search/', login_required(views.user_search), name="user-search"),
When entering data in the input field I am getting a 403 HTTP error that says I am not using the csrf_token correctly, however I have included it as I did it before and it worked the other times before...
Any idea how I can solve the 403 error?
I had to change the JS part like this:
$(document).on('keyup', '.user-search-form', function(event){
event.preventDefault();
var input = $('#user_search').val();
console.log(input);
if (input.length > 2) {
$.ajax({
type: 'POST',
url: $(this).attr('action'),
data: $(this).serialize(),
dataType: 'json',
success: function(response){
$('#results').html(response['form']);
console.log($('#results').html(response['form']));
},
error: function(rs, e){
console.log(rs.responseText);
},
});
}
else {
$('#results').empty();
}
});
and the python part in the views.py like that:
def user_search(request):
if request.method == 'POST':
search_text = request.POST.get('input')
users = User.objects.filter(username__icontains=search_text)
context = {
'users': users,
}
if request.is_ajax():
html = render_to_string('feed/user_search.html', context, request=request)
return JsonResponse({'form': html})
and now the search works!
This can easily be done with Ajax and Jquery, but this version of Django seems to be making it extra difficult. It requires the '{% csrf_token %}' (it'll throw an error without this) and that automatically submits the file when submit is pressed.
<form
id="data_upload"
method="POST"
enctype="multipart/form-data"
class="form-horizontal"
>
{% csrf_token %}
<div class="input-group mb-3">
<div class="custom-file">
<input
id="file_select"
type="file"
class="custom-file-input"
id="inputGroupFile02"
accept=".csv, .xslx"
name="file"
/>
<label
id="submit_label"
class="custom-file-label"
for="inputGroupFile02"
aria-describedby="inputGroupFileAddon02"
>Upload CSV or Excel file</label
>
</div>
<div class="input-group-append">
<button
id="upload_button"
type="submit"
class="input-group-text btn"
id="inputGroupFileAddon02"
disabled
>
Upload
</button>
</div>
</div>
<div class="d-flex justify-content-center">
<div
id="loading_div"
class="spinner-border"
role="status"
style="display: none;"
>
<span class="sr-only">Loading...</span>
</div>
</div>
</form>
Here's the ajax
$(document).ready(function () {
$("#data_upload").submit(function (event) {
event.preventDefault();
var fd = new FormData
fd.append('file', file_input[0].files[0])
$.ajax({
xhr: function () {
var xhr = new window.XMLHttpRequest()
xhr.upload.addEventListener("progress", progressHandler, false);
xhr.addEventListener("load", completeHandler, false);
xhr.addEventListener("error", errorHandler, false);
xhr.addEventListener("abort", abortHandler, false);
return xhr;
},
url: window.location.href,
type: "POST",
data: fd,
processData: false,
contentType: false,
success: function (result) {
alert('WOOOO!')
},
});
});
});
urls.py
urlpatterns = [
path('upload', UploadView.as_view(), name="upload"),
]
View.py
class UploadView(TemplateView):
def get(self, request, *args, **kwargs):
return render(request, 'upload_datatable.html')
def post(self, request, *args, **kwargs):
uploaded_file = request.FILES['file']
uploaded_file_name = uploaded_file.name
if len(uploaded_file) != 0:
if uploaded_file_name.endswith('.csv'):
file_path = self.upload_csv_to_data(uploaded_file)
elif uploaded_file_name.endswith('xlsx'):
file_path = self.upload_excel(uploaded_file)
else:
return HttpResponse({'error': 'Not valid CSV or Excel'}, content_type="application/json",
status_code=400)
else:
return HttpResponse({'error': 'No Data'}, content_type="application/json", status_code=400)
def upload_csv_to_data(self, file):
id = str(uuid.uuid4())
with open(f'data/{id}.csv', 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return f'data/{id}'
def upload_excel_to_data(self, file):
id = str(uuid.uuid4())
with open(f'data/{id}.txt', 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return f'data/{id}'
def is_csv_file(self, file):
try:
dialect = csv.Sniffer().sniff(file.read(1024))
file.seek(0)
return True
except csv.Error:
return False
def is_excel_file(self, file):
try:
book = open_workbook(file)
return True
except XLRDError as e:
return False
So when I have preventDefault to stop Django from sending anything, but when I look at network, nothing is being sent and the "WOOOOO!" isn't being printed and my breakpoint in Django at the POST endpoint isn't be triggered. So I don't think the ajax is sending the file, but at the same time I'm getting no errors. Any advice?
Even though no error was thrown when I removed
xhr: function () {
var xhr = new window.XMLHttpRequest()
xhr.upload.addEventListener("progress", progressHandler, false);
xhr.addEventListener("load", completeHandler, false);
xhr.addEventListener("error", errorHandler, false);
xhr.addEventListener("abort", abortHandler, false);
return xhr;
},
it started to work so yea.
Pass e.currentTarget when instantiating a new FormData object so you include the csrf_token in the submitted info.
...
var fd = new FormData(event.currentTarget)
fd.append('file', file_input[0].files[0])
...
I am trying to upload multiple files using Django. The idea is that while creating a blog post the user can also add images to the post. I am using Ajax to submit the blog post, however, it seems that after adding the image form the "submit" button doesn't work and my post does not get created. I have already built two models, Images and Post. Below are my codes related to this functionality. My project name is register and images are in an app called 'home':
(If I remove the image upload functionality the post is created successfully, so the ajax is working correctly)
my image model:
my post_creat view in home app views:
#login_required
def post_create(request):
data = dict()
if request.method == 'POST':
image_form = ImageForm(request.POST, request.FILES or None)
images = request.FILES.getlist('image')
form = PostForm(request.POST)
if form.is_valid() and image_form.is_valid():
post = form.save(False)
post.author = request.user
post.save()
for i in images:
image_instance = Images(image=i,post=post)
image_instance.save()
data['form_is_valid'] = True
posts = Post.objects.all()
posts = Post.objects.order_by('-last_edited')
data['posts'] = render_to_string('home/posts/home_post.html',{'posts':posts},request=request)
else:
data['form_is_valid'] = False
else:
image_form = ImageForm
form = PostForm
context = {
'form':form,
'image_form':image_form
}
data['html_form'] = render_to_string('home/posts/post_create.html',context,request=request)
return JsonResponse(data)
my javascript code for handling the ajax request:
$(document).ready(function(){
var ShowForm = function(e){
e.stopImmediatePropagation();
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType:'json',
beforeSend: function(){
$('#modal-post').modal('show');
},
success: function(data){
$('#modal-post .modal-content').html(data.html_form);
}
});
return false;
};
// change form to FormData
// var form = $(this)
// processData, contentType were removed
var SaveForm = function(e){
e.stopImmediatePropagation();
var data = new FormData($('form').get(0));
$.ajax({
url: $(this).attr('data-url'),
type: $(this).attr('method'),
data: data,
processData: false,
contentType: false,
dataType: 'json',
success: function(data){
if(data.form_is_valid){
$('#post-list div').html(data.posts);
$('#modal-post').modal('hide');
} else {
$('#modal-post .modal-content').html(data.html_form)
}
}
})
return false;
}
//create
$('.create-post-btn').click(ShowForm);
$('#modal-post').on("submit",".post-create-form",SaveForm)
//update
$('#post-list').on("click",".show-form-update",ShowForm);
$('#modal-post').on("submit",".update-form",SaveForm)
//delete
$('#post-list').on("click",".show-form-delete",ShowForm);
$('#modal-post').on("submit",".delete-form",SaveForm)
});
My post_create.html file:
<form method="POST" data-url="{% url 'home:post-create' %}" class="post-create-form" enctype="multipart/form-data">
{% csrf_token %}
<div class="modal-header">
<h5 class="modal-title" >Create a Post</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body" style="overflow-y: auto;">
{{ form|crispy }}
<button type="button" id="show-image-upload-inputs" class="btn btn-sm mr-auto btn-primary pb-1">
<span><i class="fas fa-camera"></i></span>
</button>
<div id="image-upload-div" class="mt-1" style="display: none;">
<hr class="my-2">
<p class="mx-2 text-muted small">Add up to four images to your post</p>
<div class="d-flex flex-row justify-content-between px-1">
{{ image_form }}
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Post</button>
</div>
</form>
**the display hidden is just a javascript functionality to show the form when use clicks on the vamera button.
my image model:
class Images(models.Model):
post = models.ForeignKey(Post,on_delete=models.CASCADE,related_name='images')
image = models.FileField(upload_to=upload_to_uuid('media/post_images/'),verbose_name='Image')
date_added = models.DateTimeField(auto_now_add=True)
my project (register) settings.py:
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
my project (register) urls.py;
urlpatterns = [
#Has to be included for Forgot Password funcitonality on main page
path('', include('django.contrib.auth.urls')),
path('admin/', admin.site.urls),
path('',views.user_login,name='user_login'),
path('',include('main.urls'),name='main'),
url(r'^home/',include(('home.urls','home'), namespace='home'))
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT ) + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
and my media folder is created at register/media
EDIT: I have changes my Ajax function and now I'm using FormData, however, I am getting a
Forbidden (CSRF token missing or incorrect.): /home/post/create/
[06/Apr/2020 01:18:53] "POST /home/post/create/ HTTP/1.1" 403 2513
Error,when I clikc on submit, however, I do have a csrf_token.How can I resolve this issue?
Your Code Post Model Should be like this
class Post(models.Model):
title=models.CharField(max_length=50)
sub_title=models.CharField(default="This is the subtitle of the post ",max_length=150)
content=models.TextField(max_length=4000)
date_posted=models.DateTimeField(default=timezone.now)
blog_image_1=models.ImageField(Blank=True,Null=True,upload_to='media')
blog_image_2=models.ImageField(Blank=True,Null=True,upload_to='media')
blog_image_3=models.ImageField(default='default.jpg',upload_to='media')
author =models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return self.title
The media directory be like this
MEDIA_ROOT=os.path.join(BASE_DIR,'media')
MEDIA_URL='/media/'
And Html Be like
<body>
<div class="container">
<form method="POST" enctype="multipart/form-data">
{% csrf_token %}
<fieldset class="form-group">
<legend class="'border-bottom mb-4">Post</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn-outline-info" type="submit"> Submit</button>
</div>
</form>
</div>
</body>
And Use Class Base Views They More PowerFull
class PostCreateView(LoginRequiredMixin,CreateView):
model = Post
fields = ['title','sub_title','content','blog_image_1','blog_image_2','blog_image_2']
def form_valid(self, form):
form.instance.author = self.request.user
return super().form_valid(form)