In my django project I show a list of books in template. Book model has position field which I use to sort books.
I'm trying to sort this list by drag and drop list items but my next code dont work well. I use JQuery UI. It works in frontend but dont change position field`s value when user drag and drop list item. Can someone help me to improve my js and view code. I am fused. I would be grateful for any help.
models.py:
class Book(models.Model):
title = models.CharField(max_length=200, help_text='Заголовок', blank=False)
position = models.IntegerField(help_text='Поле для сортировки', default=0, blank=True)
class Meta:
ordering = ['position', 'pk']
html:
<div id="books" class="list-group">
{% for book in books %}
<div class="panel panel-default list-group-item ui-state-default">
<div class="panel-body">{{ book.title }}</div>
</div>
{% endfor %}
</div>
urls.py:
url(r'^book/(?P<pk>\d+)/sorting/$',
BookSortingView.as_view(),
name='book_sorting')
JS:
$("#books").sortable({
update: function(event, ui) {
var information = $('#books').sortable('serialize');
$.ajax({
url: "???",
type: "post",
data: information
});
},
}).disableSelection();
views.py:
class BookSortingView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(BookSortingView, self).dispatch(request, *args, **kwargs)
def post(self, request, pk, *args, **kwargs):
for index, pk in enumerate(request.POST.getlist('book[]')):
book = get_object_or_404(Book, pk=pk)
book.position = index
book.save()
return HttpResponse()
In my django project I show a list of books in template. Book model has position field which I use to sort books.
I'm trying to sort this list by drag and drop list items but my next code dont work well. I use JQuery UI. It works in frontend but dont change position field`s value when user drag and drop list item. Can someone help me to improve my js and view code. I am fused. I would be grateful for any help.
models.py:
class Book(models.Model):
title = models.CharField(max_length=200, help_text='Заголовок', blank=False)
position = models.IntegerField(help_text='Поле для сортировки', default=0, blank=True)
class Meta:
ordering = ['position', 'pk']
html:
<div id="books" class="list-group">
{% for book in books %}
<div class="panel panel-default list-group-item ui-state-default">
<div class="panel-body">{{ book.title }}</div>
</div>
{% endfor %}
</div>
urls.py:
url(r'^book/(?P<pk>\d+)/sorting/$',
BookSortingView.as_view(),
name='book_sorting')
JS:
$("#books").sortable({
update: function(event, ui) {
var information = $('#books').sortable('serialize');
$.ajax({
url: "???",
type: "post",
data: information
});
},
}).disableSelection();
views.py:
class BookSortingView(View):
@method_decorator(csrf_exempt)
def dispatch(self, request, *args, **kwargs):
return super(BookSortingView, self).dispatch(request, *args, **kwargs)
def post(self, request, pk, *args, **kwargs):
for index, pk in enumerate(request.POST.getlist('book[]')):
book = get_object_or_404(Book, pk=pk)
book.position = index
book.save()
return HttpResponse()
Share
Improve this question
asked Aug 16, 2017 at 17:26
Nurzhan NogerbekNurzhan Nogerbek
5,25620 gold badges98 silver badges201 bronze badges
5
-
I would suggest employing some debugging to pinpoint the error. Does the ajax method post the correct data -> use
console.log()
. Does it get posted to the right URL ->'???'
can't be right. Does the python view get the parameter -> useprint
. Etc etc – Roy Prins Commented Aug 16, 2017 at 18:45 -
@RoyPrins my problem is I dont know well what exactly I need to put in that ajax's url. I tried to
url: "{% url 'book_sorting' %}"
but it`s wrong. In temninal it shows 404. JS dont understand it. For thats I am confused how to put url correctly. What can you advice to me? – Nurzhan Nogerbek Commented Aug 17, 2017 at 2:49 - "{% url 'book_sorting' %}" in your case really does not exist your url is '^book/(?P<pk>\d+)/sorting/$' so you need pass pk argument to url tag. See docs.djangoproject./en/1.11/ref/templates/builtins/#url – ikoverdyaev Commented Aug 17, 2017 at 5:45
- 1 also there is an library github./jrief/django-admin-sortable2. It makes what you want but only in a admin interface. But you can check their solution. – ikoverdyaev Commented Aug 17, 2017 at 5:49
- Thank you for your advice. There are a lot of libraries to sort items by drag and drop in admin. But i need to use it outside of admin. Anyway Thank You! =) – Nurzhan Nogerbek Commented Aug 17, 2017 at 5:54
1 Answer
Reset to default 5This is working for me!!
JS
<script type="text/javascript" charset="utf-8">
$(document).ready(function() {
$("tbody").sortable({
update: function(event, ui) {
sort =[];
window.CSRF_TOKEN = "{{ csrf_token }}";
$("tbody").children().each(function(){
sort.push({'pk':$(this).data('pk'),'order':$(this).index()})
});
$.ajax({
url: "{% url "book-sort" %}
",
type: "post",
datatype:'json',
data:{'sort':JSON.stringify(sort),
'csrfmiddlewaretoken': window.CSRF_TOKEN
},
});
console.log(sort)
},
}).disableSelection();
});
HTML
<table class="table table-hover" id="sortable" style="">
<thead>
<tr>
<th></th>
<th>Name</th>
</thead>
<tbody id="#Table">
{% for book in books %}
<tr data-pk="{{ book.id }}" class="ui-state-default" style="cursor: move;" data-placement="left" title="Customize the order by drag and drop">
<td> <a>{{ book.name }}</a> </td>
{% endfor %}
</tbody>
</table>
view
@csrf_exempt
def sort(self):
books = json.loads(self.request.POST.get('sort'))
for b in books:
book = get_object_or_404(Book, pk=int(b['pk']))
book.position = b['order']
book.save()
return HttpResponse('saved')
and also change the query_set in your listview to get the books in that order
books = Book.objects.all().order_by('position')