I have a modal window that allows me to create new instances but I'm getting some strange behaviour:
If I get an error because the site already exists the window closes
If I manage to insert the new site the window stays open
I need to reverse the behaviour.
const addBtn = document.getElementById('add-btn')
const modalBody = document.getElementById('model-body')
const siteForm = document.getElementById('site-form')
const alertBox = document.getElementById('alert-box')
const siteName = document.getElementById('id_name')
const siteCity = document.getElementById('id_city')
const csrf = document.getElementsByName('csrfmiddlewaretoken')[0].value
const handleAlerts = (type, msg) => {
alertBox.innerHTML = `
<div class="alert alert-${type}" role="alert">
${msg}
</div>
`
}
addBtn.addEventListener('click', ()=>{
siteForm.addEventListener('submit', e=>{
if (siteName.value ===''){
handleAlerts('danger', 'Name field cannot be left empty')
siteName.focus()
}else{
e.preventDefault()
const formData = new FormData()
formData.append('csrfmiddlewaretoken', csrf)
formData.append('name', siteName.value)
formData.append('city', siteCity.value)
$.ajax({
type: 'POST',
url: '/savesite/',
data: formData,
success: function(response){
handleAlerts('success', 'Site added')
siteForm.reset()
window.close();
},
error: function(error){
console.log(error)
handleAlerts('danger', 'Site already exists in that city')
},
processData: false,
contentType: false,
})
}
})
})
After changing the above code I now get the message at the console:
Scripts may close only windows that were opened by them.
This is the HTML file that opens the modal window:
{% extends 'base.html' %}
{% load static %}
{% load crispy_forms_tags %}
{% block scripts %}
<script src="{% static 'objects/home.js' %}" defer></script>
{% endblock scripts %}
{% block title %}
Site List
{% endblock title %}
{% block content %}
<!-- Modal -->
<div class="modal fade" id="addModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add Site</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="modal-body">
<div id="alert-box"></div>
<form id="site-form">
{% csrf_token %}
{{site_form|crispy}}
<button type="submit" class="btn btn-info mt-3">Save</button>
</form>
</div>
</div>
</div>
</div>
<h1>Site List</h1>
<hr>
<button type="submit" class="btn btn-danger mb-5" id="add-btn" data-bs-toggle="modal" data-bs-target="#addModal">Add new Site</button>
{% for obj in object_list %}
<div class="card mb-3">
<div class="card-body">
<h5 class="card-title">{{obj.name}}</h5>
<p class="card-text">{{obj.city}}</p>
Details
</div>
</div>
<br>
{% endfor %}
<br>
{% endblock content %}
After some struggle I think I managed to make it working. I'm sure it is not perfect but... I appretiate any comments so I can turn it better:
const addBtn = document.getElementById('add-btn')
const modalBody = document.getElementById('model-body')
const siteForm = document.getElementById('site-form')
const alertBox = document.getElementById('alert-box')
const siteName = document.getElementById('id_name')
const siteCity = document.getElementById('id_city')
const csrf = document.getElementsByName('csrfmiddlewaretoken')[0].value
const handleAlerts = (type, msg) => {
alertBox.innerHTML = `
<div class="alert alert-${type}" role="alert">
${msg}
</div>
`
}
addBtn.addEventListener('click', ()=>{
siteForm.addEventListener('submit', e=>{
if (siteName.value ===''){
e.preventDefault()
handleAlerts('danger', 'Name field cannot be left empty')
siteName.focus()
}else{
console.log('Campo preenchido')
e.preventDefault()
const formData = new FormData()
formData.append('csrfmiddlewaretoken', csrf)
formData.append('name', siteName.value)
formData.append('city', siteCity.value)
$.ajax({
type: 'POST',
url: '/savesite/',
data: formData,
success: function(response){
handleAlerts('success', 'Site added')
siteForm.reset()
window.close();
},
error: function(error){
console.log(error)
handleAlerts('danger', 'Site already exists in that city')
},
processData: false,
contentType: false,
})
}
})
})
The HTML is the same.
Related
My Django application makes divs dynamically. Each div is a post of a blog post and also I have a like button on each div. Each button will automatically turn into unlike when a user clicks on it without reloading using javascript. I wrote a javascript function for this. Unfortunately, my javascript function works only the last post on a page (As I have pagination property).
document.addEventListener("DOMContentLoaded",function(){
// const colon = document.createElement('div');
// colon.setAttribute('id','colon')
// e.preventDefault()
// const likebtn = document.createElement('button');
// likebtn.setAttribute('class','likebtn btn btn-primary');
// likebtn.setAttribute('class','likebtn');
// document.querySelector('.card-footer').appendChild(likebtn);
// document.querySelector('.likebtn').innerHTML = "Like";
document.querySelector(`#likeform${posts_id}`).addEventListener('submit',(event) => {
event.preventDefault();
like_function();
// return false;
})
// document.querySelector('.likepost').addEventListener('click', ()=> like_function('likepost'));
})
// let is_like = "{{is_like}}";
// let num_like = "{{num_like}}";
function like_function(){
// document.createElement('button').innerHTML = "Love";
// console.log("Updated!")
fetch(`/like/${posts_id}`,{
method:"POST",
body : JSON.stringify({
"is_like" : is_like,
"num_like" : num_like,
})
})
.then(response => response.json())
.then(result => {
if(result.is_like){
console.log("function is liked");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Unlike";
num_like = num_like + 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
else{
console.log("function is unliked, back off!");
console.log(`${result.is_like} for post ${posts_id}`);
let num_like = result.num_like;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#likebtn${posts_id}`).innerHTML = "Like";
num_like = num_like - 1;
console.log(`Number of posts : ${num_like}`);
document.querySelector(`#num_of_likes_${posts_id}`).innerHTML = `${num_like} `
// location.replace("http://127.0.0.1:8000")
}
})
}
// function like_function(){
// if (document.querySelector("#like").style.color == "blue"){
// document.querySelector("#like").style.color = "red";
// }else{
// document.querySelector("#like").style.color = "blue";
// }
// }
This is my full javascript code. Here I'm sharing my HTML template,
<div id="posts" class="card">
<ul class="card-body">
{% for posts in page_view %}
<li class="card">
<div class="card-header bg-success">
<h5 class="card-title"><a class="text-light" style="text-decoration: none;" href="{% url 'profile' posts.user.id %}">{{ posts.user }}</a></h5>
<h6 class="card-subtitle text-light">{{ posts.timestamp }}</h6>
</div>
<div class="card-body">
<h3 class="card-text">{{ posts.post }}</h3>
</div>
<div id="likeapost{{posts.id}}" class="card-footer">
{% if request.user in posts.likepost.all %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Unlike</button>
</form>
{% else %}
<form action="{% url 'likepost' posts_id=posts.id %}" id="likeform{{posts.id}}" method="POST" style="display: inline;">
<!-- {% csrf_token %} -->
<button id="likebtn{{posts.id}}" class="btn btn-link" type="submit">Like</button>
</form>
{% endif %}
<small id="num_of_likes_{{posts.id}}" class="num_of_likes">{{ posts.likepost.all.count }}</small>
{% block script %}
<script>
posts_id = "{{ posts.id }}";
is_like = "{{is_like}}";
num_like = "{{ posts.likepost.all.count }}";
</script>
<script src="{% static 'network/controller.js' %}"></script>
{% endblock %}
<button class="btn btn-link" style="text-decoration: none;">Comment</button>
View Post
{% if request.user.id is posts.user.id %}
Edit
{% endif %}
<!-- <div class="likepost"></div> -->
</div>
</li>
{% empty %}
<h6>No post availabel 😔</h6>
{% endfor %}
</ul>
</div>
This is my HTML template. All the buttons should work like this,
Only this one button works perfectly, but others do not. This is what happening.
What should I do? I am about 90% done. Please help.
I am trying to display user comments after they click on the comment submit button. I added an ajax call on my comment section. However when i click on the submit button after writing a comment, Page is not refreshing but it is not displaying the new comment right away. Only after i refresh the page my new comment is available. I want to display new comment on the page right after clicking the submit button without reloading the page.
I am unable to figure out what is going wrong here, my codes are as follow:
at the end of base.html
<script>
$(document).on('submit', '.comment-form', function(event){
event.preventDefault();
console.log($(this).serialize());
$.ajax({
type: 'POST',
url: $(this).attr('action'),
data: $(this).serialize(),
datatype: 'json',
success: function(response) {
$('.main-comment-section').html(response['form']);
},
error: function(rs, e) {
console.log(rs.responseText);
},
});
});
in post_detail.html, i am calling comment_section.html using the following
<div class="main-comment-section">
{% include 'webpage/comment_section.html' %}
</div>
My comment_section.html
<h1>New comment</h1>
<form method="post" class="comment-form" action=".">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="submit" class="save btn btn-outline-success">
</form>
{{ comments.count }} Comments</h3>
<!-- comments -->
{% for comment in comments %}
<article class="media comment">
<img class="rounded-circle article-img" src="{{ comment.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-profile' comment.author.username %}">{{ comment.author.first_name }} {{ comment.author.last_name }}</a>
<small class="text-muted">{{ comment.created_date }}</small>
</div>
<p class="article-content" "mr-4">{{ comment.content | linebreaks }}</p>
</div>
</article>
<div class="row">
<div class="col-1"></div>
<div class="col-10">
<div class="reply">
<div class="form-group row">
<form method="POST">
{% csrf_token %}
<input type="hidden" name="{{ comment_id }}" value="{{ comment.id }}">
{{ comment_form.as_p }}
<button type="submit" class="save btn btn-default">Comment</button>
</form>
</div>
</div>
</div>
</div>
{% empty %}
<pclass="article-content" "mr-4"> No comments here yet :(</p>
{% endfor %}
views.py
class PostDetailView(FormMixin,DetailView):
model = Post
context_object_name = 'post'
slug_url_kwarg = 'slug'
slug_field = 'slug' # DetailView's default value: optional
form_class = CommentForm
def get_success_url(self):
return reverse('post-detail', kwargs={'slug': self.object.slug})
def get_context_data(self, *args, **kwargs):
slug = self.kwargs.get("slug")
post = get_object_or_404(Post, slug=slug)
comments= Comment.objects.filter(post=post)
context = super(PostDetailView,self).get_context_data()
context['form'] = CommentForm(initial={'post': self.object, 'author': self.request.user})
context["comments"] = comments
context["post"] = post
return context
if self.request.is_ajax():
html = render_to_string('webpage/comment_section.html', context, request=self.request)
return JsonResponse({'form': html})
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super(PostDetailView, self).form_valid(form)
form.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ['author','content', 'post']
widgets = {
'content' : forms.Textarea(attrs={'class':'form-control', 'placeholder' : 'Write a comment here', 'rows':'4', 'cols': '50'}),
'author' : forms.TextInput({'class':'form-control', 'value':'', 'id':'Idspacename', 'type':'hidden'}),
'post' : forms.TextInput({'class':'form-control', 'value':'', 'id':'Idspacename', 'type':'hidden'}),
}
and urls.py
path('post/<slug:slug>/', PostDetailView.as_view(), name='post-detail'),
Please help. Thanks in advance!
I will answer on the javascript part, first you need to create wrapper for the comment list. If you get the response from success you can append the element into the wrapper.
$.ajax({
method: 'POST',
url: your_url,
data: your_data,
success(function(response) {
const comment_list = document.getElementById('comment_list');
const _el = document.createElement('article');
_el.setAttribute('class', 'media comment');
const _elImg = document.createElement('img');
_elImg.setAttribute('class', 'rounded-circle article-img')
_elImg.setAttribute('src', response.author.profile.image.url);
const mediaBody = document.createElement('div');
mediaBody.setAttribute('class', 'media-body');
const metaData = document.createElement('div');
metaData.setAttribute('class', 'article-metadata');
metaData.innerHTML = '<a class="mr-2" href="url_to_profile' + response.author.username '">' + response.author.first_name + response.author.last_name '</a><small class="text-muted">' + response.created_date + '</small>';
const commentContent = document.createElement("p");
commentContent.setAttribute("article-content mr-4");
commentContent.innerHTML = response.content;
mediaBody.appendChild(metaData);
mediaBody.appendChild(commentContent);
_el.appendChild(_elImg);
_el.appendChild(mediaBody);
})
})
<div id="comment_list">
<!-- foreach starting here and loop this below element -->
<article class="media comment">
<img class="rounded-circle article-img" src="{{ comment.author.profile.image.url }}">
<div class="media-body">
<div class="article-metadata">
<a class="mr-2" href="{% url 'user-profile' comment.author.username %}">{{ comment.author.first_name }} {{ comment.author.last_name }}</a>
<small class="text-muted">{{ comment.created_date }}</small>
</div>
<p class="article-content" "mr-4">{{ comment.content | linebreaks }}</p>
</div>
</article>
<!-- end foreach -->
</div>
The usecase of my app is to show a list of furnitures in the homepage. There is quick preview button in all those furnitures which when clicked should show its detail information. I tried to use ajax for that.
If i click on the furniture quick preview button, I get the clicked furniture slug from which I do the query and get that furniture detail information. Upto this, its working and also the modal is shown but could not show the content. How can i now show the content in the modal-body?
Here is what I have tried
def ajax_furniture_detail(request):
furniture_slug = request.GET.get('slug', None)
qs = Furniture.objects.get(slug=furniture_slug)
cart_obj, new_obj = Cart.objects.new_or_get(request)
context = {
'furniture': model_to_dict(qs),
'cart': model_to_dict(cart_obj),
'status': 'ok'
}
return JsonResponse(context)
{% block content %}
{% include 'furnitures/furnitures_home.html'%}
{% endblock content %}
{% block js %}
{{ block.super }}
<script>
$(document).ready(function(){
$('.quick-view-button').click(function() {
var _this = $(this);
var slug = _this.attr("data-slug");
$.ajax({
url: '/ajax/furniture',
type: "get",
data: {'slug': slug},
success: function(data) {
$('#product-quick-view-modal').modal('show');
$('#product-quick-view-modal').find('.modal-body').html(data.html);
},
error: function(err) {
console.log('error', err);
}
})
})
});
</script>
{% endblock js %}
furnitures_home.html
{% load static %}
<div class="furnitures" id="content">
{% for furniture in furnitures %}
{% if forloop.first %}<div class="row products">{% endif %}
<div class="col-md-4 col-sm-3">
<div class="product">
<div class="image" style="height: 205px;">
<div class="quick-view-button" data-slug={{ furniture.slug }}>
Quick view
</div>
{% endif %}
</div>
</div>
</div>
{% endfor %}
</div>
<div class="modal fade" id="product-quick-view-modal" tabindex="-1" role="dialog" aria-hidden="false" style="display: none;">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-body">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<p>Hello</p>
<p>{{furniture.name}}</p>
</div>
</div>
</div>
<!--/.modal-dialog-->
</div>
One neat way to do this is to use a snippet html for product detail and send the product detail html snippet using render_to_string and just replace that html snippet in the modal.
rendered = render_to_string('product_detail_snippet.html', context,
context_instance=RequestContext(request))
return JsonResponse({'product_snippet': rendered})
And in the ajax success:
$('#product-quick-view-modal').find('.modal-body').html(data.product_snippet);
I have little problem in my Django application. I am tring to use modal from bootstrap 4 and ajax to create new object. Here below you see code that I used. When user click the button I dont see modal window but background became grey. What I did wrong? Why I dont see modal? Is my ajax correct?
detail.html:
<!-- BUTTON TO TRIGGER THE ACTION -->
<button class="add-group-task" data-toggle="modal" data-target="#add-group-task-modal" data-url="{% url 'project:group_task_add' project_code=project.code %}">{% trans 'Create' %}</button>
<table class="table table-bordered" id="group-tasks-table">
<!-- TABLE CONTENT-->
</table>
<!--MODAL-->
<div class="modal fade" id="add-group-task-modal" tabindex="-1" role="dialog" aria-labelledby="add-group-task-modal-title" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
</div>
</div>
</div>
urls.py:
url(r'^(?P<project_code>[0-9a-f-]+)/add_new_group_task/$', group_task_add, name='group_task_add'),
view.py:
def group_task_add(request, project_code):
data = dict()
project = get_object_or_404(Project, pk=project_code)
if request.method == 'POST':
form = GroupTaskAddForm(request.POST)
if form.is_valid():
group_task = form.save(commit=False)
group_task.project = project
group_task.save()
data['form_is_valid'] = True
group_tasks = GroupTask.objects.filter(project=project_code)
data['html_group_tasks'] = render_to_string('project/project_detail.html', {'group_tasks': group_tasks})
else:
data['form_is_valid'] = False
else:
form = GroupTaskAddForm()
context = {'form': form}
data['html_group_task_add_form'] = render_to_string('project/group_task_add.html', context, request=request)
return JsonResponse(data)
javascript:
$(function () {
/* Functions */
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#add-group-task-modal").modal("show");
},
success: function (data) {
$("#add-group-task-modal .modal-content").html(data.html_form);
}
});
};
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#group-tasks-table tbody").html(data.html_group_tasks);
$("#add-group-task-modal").modal("hide");
}
else {
$("#add-group-task-modal .modal-content").html(data.html_group_task_add_form);
}
}
});
return false;
};
// Create book
$(".add-group-task").click(loadForm);
$("#add-group-task-modal").on("submit", ".js-group-task-add-form", saveForm);
});
group_task_add.html:
<form method="post" action="{% url 'project:group_task_add' project_code=project.code %}" class="js-group-task-add-form">
{% csrf_token %}
<div class="modal-header">
<h5 class="modal-title" id="addGroupTaskModalLabel">{% trans 'Create a new group task' %}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="formGroupTaskInput">{% trans 'Name' %}</label>
{{ form.name }}
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">{% trans 'Close' %}</button>
<button type="submit" class="btn btn-primary">{% trans 'Create' %}</button>
</div>
</form>
ERROR:
try with following html and js code combination:
<!-- BUTTON TO TRIGGER THE ACTION -->
<button ... onclick="modalHandler()">{% trans 'Create' %}</button>
// js code
function modalHandler(){
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#add-group-task-modal").modal("show");
},
success: function (data) {
$("#add-group-task-modal .modal-content").html(data.html_form);
}
});
};
What this code is supposed to do is let a user click they're description and be able to edit it. I have the modal popping up, but the save button will not save the data and produces the following error:
Uncaught ReferenceError: csrftoken is not defined
at HTMLButtonElement.<anonymous> (modalShortListDescription.js:6)
at HTMLButtonElement.dispatch (jquery.min.js:3)
at HTMLButtonElement.r.handle (jquery.min.js:3)
Here's where the modal is called:
<div class="tab-content col-xs-12">
{% for list in lists %}
<input type="hidden" id="idList" id_list="{{list.id}}">
{% if forloop.first and not createTabActive %}
<div role="tabpanel" class="tab-pane fade active in" id="list{{list.id}}">
{% else %}
<div role="tabpanel" class="tab-pane fade" id="list{{list.id}}">
{% endif %}
<div class="content col-xs-12">
<div class="form-horizontal sort-by col-xs-12">
<h3>Description</h3>
{% if list.description %}
{{list.description}}
{% else %}
None
{% endif %}
{% include "layout/popUp/modal-short-list-description.html" %}
</div>
Here's the modal itself:
<div class="modal fade" id="modalDescription{{list.id}}" role="dialog">
<div class="modal-dialog">
<form class="form-horizontal" action="{% url 'update-list-description' %}" method="post">
{% csrf_token %}
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Description</h4>
</div>
<div class="modal-body modal-body-exper modal-body-value modal-body-t">
<div class="lineEnterValue lineTeamSize lineTitle">
<div class="form-group {% if form.description.errors %} has-error{% elif form.is_bound %} has-success{% endif %}">
<div class="col-sm-10">
<textarea name="{{ form.description.html_name }}" class="form-control" id="{{ form.description.id_for_label }}" rows="5" style="margin: 0px; height: 90px; width: 455px;"></textarea>
</div>
{% if form.description.errors %}
<ul class="col-sm-10 col-sm-offset-2 error-list text-danger">
{% for error in form.description.errors %}
<li>{{ error|escape }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
</div>
</div>
<div class="modal-footer modal-footer-value">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary" id="description_save">Save</button>
</div>
</div>
</form>
</div>
Here is the .js that the save button uses:
$(document).ready(function() {
$("#description_save").click(function() {
var description = $("#form.description").val();
var idList = $("#idList").attr("id_list");
var url = "/bid/update-list-description";
csrftoken();
$.ajax({
type: "POST",
url: url,
data: {description : description, idList: idList},
}).done(function(response){
$(".modalDescription").modal("hide");
$(".editDescription").text(description);
});
})
})
EDIT:
views.py:
#csrf_protect
def updateListDescription(request):
checkEmployer(request)
pageClass="my-short-lists search-for-prospect"
#shortList = get_object_or_404(List, id = request.POST.get("idList"))
shortList = request.user.profile.profile_employers.employer_lists.filter(pk=request.POST.get("idList"))
if request.method =="POST":
form = ListForm(request.POST)
if form.is_valid():
shortList.description = form.cleaned_data["description"]
shortList.save()
else:
form = ListForm()
return redirect('my-short-lists')
EDIT:
I think the problem lies in not only csrftoken, but also in the button: if a button calls ajax, it should not be submit. If it posts the form, it should not do ajax call. It seems that you add the token in the form, but ajax does his thing first... So the first answer seems valid.
Or,
You can instead add a header to every ajax call in $.ajaxSetup(). The DOC has this part explained:
Define the getCookie(name) method;
Define var csrftoken = getCookie('csrftoken');;
Use these lines:
That is:
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);
}
}
});
Then you don't have to change any ajax call. The header is attached in every ajax call.
https://docs.djangoproject.com/en/2.0/ref/csrf/, under "Ajax" section.
I have used this approach and it worked.
The AJAX POST doesn't include the csrf_token. Add:
'csrfmiddlewaretoken': $('[name="csrfmiddlewaretoken"]').val()
into $.ajax data (along with description and idList) and remove csrftoken().
Edit your js to this
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;
}
$(document).ready(function() {
$("#description_save").click(function() {
var description = $("#form.description").val();
var idList = $("#idList").attr("id_list");
var url = "/bid/update-list-description";
var csrftoken = getCookie('csrftoken');
$.ajax({
type: "POST",
url: url,
data: {description : description,
idList: idList,
csrfmiddlewaretoken: csrf_token
},
}).done(function(response){
$(".modalDescription").modal("hide");
$(".editDescription").text(description);
});
})
})