Skip to content

Instantly share code, notes, and snippets.

@oisobstudio oisobstudio/part.md

Last active Jul 11, 2020
Embed
What would you like to do?
Django Pagination Server-Side Menggunakan DataTable

myapp/views.py

import json

from django.views.generic import View
from django.http import HttpResponse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from django.core.serializers.json import DjangoJSONEncoder

# ================
# Inner app module
# ================
from .models import Invoice
from .models import TransactionDetail 
from .models import InvoiceCategory
from .models import InvoiceStatus


class AjaxInvoiceWebList(View):

	def post(self, request):
		# Ambil semua data invoice yang valid
		invoices = self._datatables(request)
		return HttpResponse(json.dumps(invoices, cls=DjangoJSONEncoder), content_type='application/json')
		
	def _datatables(self, request):
		datatables = request.POST
		# Ambil draw
		draw = int(datatables.get('draw'))
		# Ambil start
		start = int(datatables.get('start'))
		# Ambil length (limit)
		length = int(datatables.get('length'))
		# Ambil data search
		search = datatables.get('search[value]')
		# Set record total
		records_total = Invoice.objects.all().exclude(Q(transactiondetail=None)|Q(shipping=None)|Q(billing=None)).count()
		# Set records filtered
		records_filtered = records_total
		# Ambil semua invoice yang valid
		invoices = Invoice.objects.all().exclude(Q(transactiondetail=None)|Q(shipping=None)|Q(billing=None))

		if search:
			invoices = Invoice.objects.filter(
					Q(invoice_number__icontains=search)|
					Q(user__username__icontains=search)|
					Q(category__info__icontains=search)|
					Q(status__info__icontains=search)
				).exclude(Q(transactiondetail=None)|Q(shipping=None)|Q(billing=None))
			records_total = invoices.count()
			records_filtered = records_total

		# Atur paginator
		paginator = Paginator(invoices, length)

		try:
			object_list = paginator.page(draw).object_list
		except PageNotAnInteger:
			object_list = paginator.page(draw).object_list
		except EmptyPage:
			object_list = paginator.page(paginator.num_pages).object_list


		data = [
			{
				'user': inv.user.username,
				'invoice_number': inv.invoice_number,
				'date_transaction': inv.invoice_date,
				'total_price': inv.total,
				'category': inv.category.info,
				'status': inv.status.info
			} for inv in object_list
		]

		return {
			'draw': draw,
			'recordsTotal': records_total,
			'recordsFiltered': records_filtered,
			'data': data,
		}
		
def invoiceweb_list(request):
    data_context = {}
    return render(request, 
				  'myapp/invoice/invoiceweb_list.html', 
				  data_context)

myapp/urls.py

from django.conf.urls import url
from . import views


urlpatterns = [
	url(r'^invoice/web\.html$', 
		views.invoiceweb_list, 
		name='invoiceweb_list'),
	url(r'^ajax/invoice/web\.html$', 
		views.AjaxInvoiceWebList.as_view(), 
		name='ajax_invoice_web_list'),
]

project/urls.py

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
	# ....
    url(r'^transaction/', include('apltransaction.urls', namespace="apltransaction")),
]

myapp/templates/myapp/invoice/invoiceweb_list.html

{% extends "base.html" %}
{% load staticfiles %}
{% load widget_tweaks %}

{% block title %}Invoice In Web{% endblock %}

{% block heading %}Invoice In Web{% endblock %}

{% block css %}
<link rel="stylesheet" type="text/css" href="{% static 'bower_components/datatables/css/dataTables.bootstrap.min.css' %}">
{% endblock %}

{% block content %}
<table id="example" class="display table" cellspacing="0" width="100%">
    <thead>
        <tr>
            <th>#</th>
            <th>User</th>
            <th>Invoice Number</th>
            <th>Date Transaction</th>
            <th>Total Price</th>
            <th>Category</th>
            <th>Status</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
            <th><input type="checkbox" name="checkbox"></th>
            <th>User</th>
            <th>Invoice Number</th>
            <th>Date Transaction</th>
            <th>Total Price</th>
            <th>Category</th>
            <th>Status</th>
        </tr>
    </tfoot>
</table>
{% endblock %}

{% block js %}
<script src="{% static 'bower_components/datatables/js/dataTables.bootstrap.min.js' %}"></script>
<script>
    $(document).ready(function() {
        $('#example').DataTable( {
            "processing": true,
            "serverSide": true,
            "ajax": {
                "url": "url 'apltransaction:ajax_invoice_web_list'",
                "type": "POST"
            },
            "columns": [
                { "data": "user" },
                { "data": "user" },
                { "data": "invoice_number" },
                { "data": "date_transaction" },
                { "data": "total_price" },
                { "data": "category" },
                { "data": "status" }
            ]
        } );
    } );
</script>
{% endblock %}
@diogosimao

This comment has been minimized.

Copy link

diogosimao commented Sep 1, 2018

Works in parts!

@h4rm41n

This comment has been minimized.

Copy link

h4rm41n commented Sep 11, 2018

this is awesome trick for datatables server side on django
sorry please correct the js client code if type POST request

"ajax": {
        "url": "{% url 'app_url:ajax_web_list' %}",
        "type": "post",
        "data": {
            "csrfmiddlewaretoken": "{{ csrf_token }}"
        }
    }
"ajax": {
        "url": "{% url 'app_url:ajax_web_list' %}",
        "type": "get",
    }
@chalist

This comment has been minimized.

Copy link

chalist commented Nov 21, 2018

Where you use start variable?

@dsifat

This comment has been minimized.

Copy link

dsifat commented Nov 29, 2018

Is this working perfectly?

@chalist

This comment has been minimized.

Copy link

chalist commented Dec 1, 2018

Does not work for me!

@rodrigosobrero

This comment has been minimized.

Copy link

rodrigosobrero commented Dec 11, 2018

Pagination it's wrong, you need to change to this:

page_number = start / length + 1

try:
    object_list = paginator.page(page_number).object_list
except PageNotAnInteger:
    object_list = paginator.page(1).object_list
except EmptyPage:
    object_list = paginator.page(1).object_list
@Ildemselcuk

This comment has been minimized.

Copy link

Ildemselcuk commented May 31, 2019

Thank you for coding of datatables with Django.
I run to above code . But line of "draw = int(datatables.get('draw')) " take following errors.
"TypeError: int() argument must be a string, a bytes-like object or a number, not 'NoneType'"

@guhkun13

This comment has been minimized.

Copy link

guhkun13 commented Apr 6, 2020

hi, thanks for the code, it works after applied the solution in comment sections (also thanks to contributor) , it really help me!

btw, the sorting does not work , so i add these lines :

  • Ambil data untuk ordering

`

order_idx = int(datatables.get('order[0][column]'))
order_dir = datatables.get('order[0][dir]')
order_col = 'columns[' + str(order_idx) + '][data]'
order_col_name = datatables.get(order_col)

if (order_dir == "desc"):
  order_col_name =  str('-' + order_col_name)

... (code filtering data)

  • after data filterred , apply order
    datas = datas.order_by(order_col_name)

it's just there is still this bug, the data in first row is not sorted. still try to figure out the solutions

@guhkun13

This comment has been minimized.

Copy link

guhkun13 commented Apr 11, 2020

update, i found this column filtering in datatables but it's for client side rendering ( https://datatables.net/extensions/fixedheader/examples/options/columnFiltering.html )
so i added it to able using server side, cont from code above

        idx=0
        for itemcol in datatables:
            colname = 'columns['+str(idx)+'][data]'
            colsearchval = 'columns['+str(idx)+'][search][value]'

            colname = datatables.get(colname)
            colsearchval = datatables.get(colsearchval)
            if (colsearchval):
                search_type = 'icontains'
                filter = colname + '__' + search_type
                datas=datas.filter(**{ filter: colsearchval })

                records_total = datas.count()
                records_filtered = records_total

            idx+=1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.