Closed rg3915 closed 4 years ago
Vendo o exemplo Server-side processing e seguindo a doc Server-side processing, temos que:
A partir do endpoint /person/json/
devemos passar como parâmetros da url
?start=0&length=10
E a API deve retornar
response = {
'data': data,
'page': page,
'per_page': per_page,
'recordsTotal': total,
'recordsFiltered': total,
}
Se você não informar
recordsTotal
erecordsFiltered
ele não vai mostrar os itens total, consequentemente não vai mostrar a paginação completa.
Então:
1.1 Eu criei um endpoint que me retorna os dados em JSON.
Os dados são paginados de 10 em 10.
path('person/json/', v.person_json, name='person_json'),
1.2 Montei um dicionário no models pra me retornar os dados
class Person(models.Model):
name = models.CharField('nome', max_length=100)
email = models.EmailField(null=True, blank=True)
phone = models.CharField('telefone', max_length=11, null=True, blank=True)
GENDER = (
('0', ''),
('man', 'homem'),
('woman', 'mulher'),
)
gender = models.CharField(
'sexo',
max_length=5,
choices=GENDER,
default='0'
)
def to_dict_json(self):
return {
'pk': self.pk,
'name': self.name,
'email': self.email,
'phone': self.phone,
'gender': self.get_gender_display(),
}
1.3 Em views eu monto uma list compreehension que me retorna os dados em JSON.
persons = Person.objects.all()
data = [person.to_dict_json() for person in persons]
response = {
'data': data,
}
return JsonResponse(response)
persons_serverside.html
{% extends "base.html" %}
{% load static %}
{% block content %}
<div class="jumbotron">
<div class="container">
<h2>Exemplo do uso de <a href="https://datatables.net/" target="_blank">DataTables</a></h2>
<p>Exemplo do uso de DataTables em <a href="https://datatables.net/examples/data_sources/server_side.html" target="_blank">Server-side render processing</a> com Django.</p>
</div>
</div>
<div class="container">
<div class="row">
<div class="cols">
<h2>DataTables Server-side render </h2>
<table id="myTable" class="table">
<thead>
<tr>
<th>Nome</th>
<th>E-mail</th>
<th>Telefone</th>
<th>Gênero</th>
</tr>
</thead>
</table>
</div>
</div>
<hr>
</div> <!-- /container -->
{% endblock content %}
{% block js %}
<script>
$(document).ready( function () {
$('#myTable').DataTable({
"processing": true,
"serverSide": true,
"ajax": "/person/json/",
"columns": [
{"data": "name"},
{"data": "email"},
{"data": "phone"},
{"data": "gender"}
]
});
});
</script>
{% endblock js %}
Repare nas opções:
"processing": true,
"serverSide": true,
"ajax": "/person/json/",
2.1 views.py
def persons_serverside(request):
template_name = 'persons_serverside.html'
return render(request, template_name)
def person_json(request):
persons = Person.objects.all()
total = persons.count()
_start = request.GET.get('start')
_length = request.GET.get('length')
if _start and _length:
start = int(_start)
length = int(_length)
page = math.ceil(start / length) + 1
per_page = length
persons = persons[start:start + length]
data = [person.to_dict_json() for person in persons]
response = {
'data': data,
'page': page, # [opcional]
'per_page': per_page, # [opcional]
'recordsTotal': total,
'recordsFiltered': total,
}
return JsonResponse(response)
O DataTable me fornece start
e length
via GET.
E eu uso o mesmo para fazer um fatiamento nos registros:
persons = persons[start:start + length]
E por fim
...
'recordsTotal': total,
'recordsFiltered': total,
...
PS: na verdade eu precisava de page
e per_page
por causa da API original, não é por causa do DataTable em si. Tanto que eu fiz o slice usando apenas start
e length
.
No final o DataTable só precisa disso:
response = {
'data': data,
'recordsTotal': total,
'recordsFiltered': total,
}
Thank you @rg3915 this worked for me :)
https://datatables.net/examples/data_sources/server_side.html