django-datatables-view is a base view for handling server side processing for the awesome datatables 1.9.x, 1.10.x (http://datatables.net).,django-datatables-view simplifies handling of sorting, filtering and creating JSON output, as defined at: http://datatables.net/examples/server_side/,Example project that uses django-datatables-view is available at: https://bitbucket.org/pigletto/django-datatables-view-example/,django_datatables_view uses GenericViews, so your view should just inherit from base class: BaseDatatableView, and override few things (there is also a DatatableMixin - pure datatables handler that can be used with the mixins of your choice, eg. django-braces). These are:
1. Install django-datatables-view
pip install django - datatables - view
See example below:
from django_datatables_view.base_datatable_view import BaseDatatableView from django.utils.html import escape class OrderListJson(BaseDatatableView): # The model we 're going to show model = MyModel # define the columns that will be returned columns = ['number', 'user', 'state', 'created', 'modified'] # define column names that will be used in sorting # order is important and should be same as order of columns # displayed by datatables.For non - sortable columns use empty # value like '' order_columns = ['number', 'user', 'state', '', ''] # set max limit of records returned, this is used to protect our site if someone tries to attack our site # and make it return huge amount of data max_display_length = 500 def render_column(self, row, column): # We want to render user as a custom column if column == 'user': # escape HTML for security reasons return escape('{0} {1}'.format(row.customer_firstname, row.customer_lastname)) else: return super(OrderListJson, self).render_column(row, column) def filter_queryset(self, qs): # use parameters passed in GET request to filter queryset # simple example: search = self.request.GET.get('search[value]', None) if search: qs = qs.filter(name__istartswith = search) # more advanced example using extra parameters filter_customer = self.request.GET.get('customer', None) if filter_customer: customer_parts = filter_customer.split(' ') qs_params = None for part in customer_parts: q = Q(customer_firstname__istartswith = part) | Q(customer_lastname__istartswith = part) qs_params = qs_params | q if qs_params else q qs = qs.filter(qs_params) return qs
Add typical django's urlconf entry:
url(r '^my/datatable/data/$', login_required(OrderListJson.as_view()), name = 'order_list_json'),
Another example of views.py customisation
from django_datatables_view.base_datatable_view
import BaseDatatableView
from django.utils.html
import escape
class OrderListJson(BaseDatatableView):
order_columns = ['number', 'user', 'state']
def get_initial_queryset(self):
#
return queryset used as base
for further sorting / filtering
# these are simply objects displayed in datatable
# You should not filter data returned here by any filter values entered by user.This is because
# we need some base queryset to count total number of records.
return MyModel.objects.filter(something = self.kwargs['something'])
def filter_queryset(self, qs):
# use request parameters to filter queryset
# simple example:
search = self.request.GET.get('search[value]', None)
if search:
qs = qs.filter(name__istartswith = search)
# more advanced example
filter_customer = self.request.GET.get('customer', None)
if filter_customer:
customer_parts = filter_customer.split(' ')
qs_params = None
for part in customer_parts:
q = Q(customer_firstname__istartswith = part) | Q(customer_lastname__istartswith = part)
qs_params = qs_params | q
if qs_params
else q
qs = qs.filter(qs_params)
return qs
def prepare_results(self, qs):
# prepare list with output column data
# queryset is already paginated here
json_data = []
for item in qs:
json_data.append([
escape(item.number), # escape HTML
for security reasons
escape("{0} {1}".format(item.customer_firstname, item.customer_lastname)),
# escape HTML
for security reasons
item.get_state_display(),
item.created.strftime("%Y-%m-%d %H:%M:%S"),
item.modified.strftime("%Y-%m-%d %H:%M:%S")
])
return json_data
This sample assumes that list of columns and order columns is defined on the client side (DataTables), eg.:
$(document).ready(function() {
var dt_table = $('.datatable').dataTable({
order: [
[0, "desc"]
],
columns: [{
data: 'name',
orderable: true,
searchable: true
},
{
data: 'description',
orderable: true,
searchable: true,
}
],
searching: true,
processing: true,
serverSide: true,
stateSave: true,
ajax: TESTMODEL_LIST_JSON_URL
});
});
Second, what have I tried so far: My structure for this project was like this:
-Project manage.py - myapp(folder) views.py models.py urls.py - datatableview * (folder) - projectapp(folder) settings.py urls.py
In myapp>models:
class Post(models.Model):
title = models.CharField(max_length = 150)
body = models.TextField()
created = models.DateField()
In myapp>views:
class MyView(DatatableView):
model = Post
datatable_options = {
'columns': [
'title',
'body',
'created',
]
}
In templates: in (tempaltes/myapp/post_list.html)
{
% block content %
} {
{
datatable
}
} {
{
object_list
}
} {
% endblock %
}
Result was like this:
title body created
[<post: one>, <post: two>]
With django-datatables-view, basically you have to provide a DatatablesView-derived view to describe the desired table content and behaviour, and the app manages the interaction with DataTables.net by reacting to the ajax requests with suitable responses.,To provide server-side rendering of a Django Model, you need a specific view derived from DatatablesView() which will be called multiple times via Ajax during data navigation.,django-datatables-view is a Django app which provides the integration of a Django project with the jQuery Javascript library DataTables.net, when used with server-side processing mode.,DatatablesView will serialize the required data during table navigation; in order to render the initial web page which should contain the table, you need another "application" view, normally based on a template.
pip install git + https: //github.com/morlandi/django-datatables-view
pip install git + https: //github.com/morlandi/django-datatables-view@v3.0.0
INSTALLED_APPS = [
...
'datatables_view',
]
{% block extrastyle %}
<link href="{% static 'datatables_view/css/style.css' %}" rel="stylesheet" />
<link rel='stylesheet' href="{% static 'datatables.net-bs/css/dataTables.bootstrap.min.css' %}"></script>
<link rel='stylesheet' href="{% static 'datatables.net-buttons-bs/css/buttons.bootstrap.min.css' %}"></script>
{% endblock extrastyle %}
{% block extrajs %}
<script type="text/javascript" src="{% static 'datatables_view/js/utils.js' %}"></script>
<script src="{% static 'datatables.net/js/jquery.dataTables.min.js' %}"></script>
<script src="{% static 'datatables.net-bs/js/dataTables.bootstrap.min.js' %}"></script>
<script src="{% static 'datatables.net-buttons/js/dataTables.buttons.min.js' %}"></script>
<script src="{% static 'datatables.net-buttons/js/buttons.print.min.js' %}"></script>
<script src="{% static 'datatables.net-buttons/js/buttons.html5.min.js' %}"></script>
<script src="{% static 'datatables.net-buttons-bs/js/buttons.bootstrap.min.js' %}"></script>
<script src="{% static 'jszip/dist/jszip.min.js' %}"></script>
<script src="{% static 'pdfmake/build/pdfmake.min.js' %}"></script>
<script src="{% static 'pdfmake/build/vfs_fonts.js' %}"></script>
{% endcompress %}
from django.urls
import path
from.import datatables_views
app_name = 'frontend'
urlpatterns = [
...
path('datatable/registers/', datatables_views.RegisterDatatablesView.as_view(), name = "datatable_registers"),
]
from django.contrib.auth.decorators
import login_required
from django.utils.decorators
import method_decorator
from datatables_view.views
import DatatablesView
from backend.models
import Register
@method_decorator(login_required, name = 'dispatch')
class RegisterDatatablesView(DatatablesView):
model = Register
title = 'Registers'
column_defs = [{
'name': 'id',
'visible': False,
}, {
'name': 'created',
}, {
'name': 'type',
}, {
'name': 'address',
}, {
'name': 'readonly',
}, {
'name': 'min',
}, {
'name': 'max',
}, {
'name': 'widget_type',
}]
© 2019-2021 All rights reserved
You just make an HTML table, add a loop in Django template to display contents of table and then initialize this table with a JavaScript call.
<table id="myDataTable">
... table contents
</table>
<script>
$(document).ready( function () {
$('#myDataTable').DataTable();
} );
</script>
Create an .env
file with the following contents:
DATABASE_URL = postgresql: //djangito:djangito@db/djangito
REDIS_URL = redis: //redis/0
DJANGO_SECRET_KEY = 123
DJANGO_DEBUG = True
Now let's create an django application where we will put models, views and templates for this tutorial.
docker - compose run web python manage.py startapp datatable
Edit datatable/admin.py
to register our models in Django Admin:
from django.contrib
import admin
from datatable.models
import Order, OrderLine, Client
admin.site.register(Order)
admin.site.register(OrderLine)
admin.site.register(Client)
Create a file datatable/tuples.py
with this code:
from collections
import namedtuple
ORDER_STATUSES = namedtuple('ORDER_STATUSES', 'proposal in_progress done rejected')._make(range(4))
I'm not familiar with Django, but if it's getting data returned, albeit just a single row, then I'd say the URL aspect is working fine and the problem would be in the view or the script that accesses the database.,Thanks for the response Colin. Yeah, it needs to be solved in the view. I have this code which works, but it's a cludge. I'd like to see a better way of doing this.,It returns the single row in the data base:,I'm not familiar with Django but it looks like you second version of Sensor_asJson is doing some extra work. Looks like line 3 (serialized_objects = serializers.serialize('json', object_list)) is creating a json string but then you are parsing the string back to a Python object in line 4. So I think object_list in line 2 and json_objects in line 4 are effectively the same.
I initialize datatable with this:
$(document).ready(function() {
$('#mytable').DataTable({
"ajax": {
"processing": true,
"dataSrc": "",
"url": "{% url 'Sensor_ajax_url' %}"
}
});
});
my view looks like this:
def Sensor_asJson(request):
object_list = Sensor.objects.all()
json = serializers.serialize('json', object_list)
return HttpResponse(json, content_type = 'application/json;charset=utf-8')
It returns the single row in the data base:
[{
"model": "sensors.sensor",
"pk": 4,
"fields": {
"userid": 1,
"update_date": "2019-03-09T19:15:58Z",
"status": false,
"name": "sidedoor",
"zone": "firstfloor"
}
}]
My view now looks like this:
def Sensor_asJson(request):
object_list = Sensor.objects.all()
serialized_objects = serializers.serialize('json', object_list)
json_objects = json.loads(serialized_objects)
list_objects = []
for index in range(len(json_objects)):
list_objects.append(json_objects[index]['fields'])
return HttpResponse(json.dumps(list_objects), content_type = 'application/json;charset=utf-8')
My dataTables init look like this:
$(document).ready(function() {
$('#mytable').DataTable({
"ajax": {
"processing": true,
"dataSrc": "",
"url": "{% url 'Sensor_ajax_url' %}"
},
"columns": [{
"data": "userid"
},
{
"data": "update_date"
},
{
"data": "status"
},
{
"data": "name"
},
{
"data": "zone"
}
]
});
});
My url.py file is:
urlpatterns = [
path('show', views.show, name = 'show_template'),
path('', views.Sensor_asJson, name = 'Sensor_ajax_url'),
]
In your first post you have this json response:
[{
"model": "sensors.sensor",
"pk": 4,
"fields": {
"userid": 1,
"update_date": "2019-03-09T19:15:58Z",
"status": false,
"name": "sidedoor",
"zone": "firstfloor"
}
}]
Your columns.data
config will look like this:
"columns": [{
"data": "fields.userid"
},
{
"data": "fields.update_date"
},
{
"data": "fields.status"
},
{
"data": "fields.name"
},
{
"data": "fields.zone"
}
]
You might be able to re-write this code:
list_objects = []
for index in range(len(json_objects)):
list_objects.append(json_objects[index]['fields'])
This is a long way of saying your second version could look like this to eliminate the nested objects:
def Sensor_asJson(request):
object_list = Sensor.objects.all()
list_objects = [x['fields']
for x in object_list
]
return HttpResponse(json.dumps(list_objects), content_type = 'application/json;charset=utf-8')
Thanks for the response. I did try and convert the queryset response to a list object with list(object_list) and then tried to iterate over the list to grab the "fields" values. I kept getting "Sensor object is not subscriptable". I get the same error with the listcomp.
[12/Mar/2019 16:02:52] "GET /tablesensors/show HTTP/1.1" 200 5534
Internal Server Error: /tablesensors/
Traceback (most recent call last):
File "/home/ubuntu/django-apps/doorenv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/ubuntu/django-apps/doorenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ubuntu/django-apps/doorenv/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ubuntu/django-apps/doorstatus/tablesensors/views.py", line 23, in Sensor_asJson
list_objects = [x['fields'] for x in object_list]
File "/home/ubuntu/django-apps/doorstatus/tablesensors/views.py", line 23, in <listcomp>
list_objects = [x['fields'] for x in object_list]
TypeError: 'Sensor' object is not subscriptable
Its hard to say without knowing what the sensor object contains. You might need to loop through it they way you have originally:
list_objects = []
for index in range(len(json_objects)):
list_objects.append(json_objects[index]['fields'])
NAC – Helmond Sport : Statistics and analysis (05-08-2022)
In this particular series I use a very small dataset of football clubs with their stadium, capacity, and characteristics. The model we will be using for creating the table is called Tabledata.
models.py
class TableData(models.Model):
name = models.CharField(max_length = 200, unique = True)
attendance = models.IntegerField(blank = True, null = True)
stadium = models.CharField(max_length = 200, blank = True, null = True)
characteristics = models.ManyToManyField(Characteristics, blank = True, null = True)
created_at = models.DateTimeField(auto_now_add = True)
edited_at = models.DateTimeField(auto_now = True)
def __str__(self):
return self.name
The first thing on our list is creating a url endpoint for our Json reponse. Go to your urls.py file and create the new endpoint (in red below):
urls.py
from django.contrib
import admin
from django.urls
import path, include
from table
import views as view
urlpatterns = [
path('table1/', view.table1, name = 'table1'),
path('multiplechoicefield/', view.modelmultiplechoicefield, name = 'modelmultiplechoicefield'),
path('', view.home, name = 'home'),
path('jsonresponse/footballclubs', view.footballclubs, name = 'footballclubs'),
]
Next, we need to create a view called footballclubs where we create the Json reponse. On top of our views.py file we import the Json reponse package. Below the import we write the logic for our response. In the view we create a list based on our TableData objects. With the .values() command we can specify which fields we want to include in the response.
views.py
from django.http
import JsonResponse
def footballclubs():
result_list = list(TableData.objects.all()\
.values('name',
'attendance',
'stadium',
'created_at',
'edited_at',
'id',
))
return JsonResponse(result_list, safe = False)
Second, we create view for the template where we specify the html template.
views.py
def table2(request):
context = {}
return render(request, 'table/table2.html', context)
Last, we create a url endpoint (green below) for our view in the urls.py file.
urls.py
from django.contrib
import admin
from django.urls
import path, include
from table
import views as view
urlpatterns = [
path('table1/', view.table1, name = 'table1'),
path('table2/', view.table2, name = 'table2'),
path('multiplechoicefield/', view.modelmultiplechoicefield, name = 'modelmultiplechoicefield'),
path('', view.home, name = 'home'),
path('jsonresponse/footballclubs', view.footballclubs, name = 'footballclubs'),
]