mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-07 07:36:20 +01:00
5.7 KiB
5.7 KiB
DataTables Server Side Rendering
The allianceauth.framework.datatables.DataTablesView module provides a simple class based view to
implement simple server side filtering ordering and searching of DataTables.
This is intended to make the life of our community apps developer a little easier, so they don't have to reinvent the wheel.
Usage
To use this view is as easy as defining your stub templates, and fields and adding the view to the urls.py
Given the EveCharacter Model as our model of choice we would define our stubs like so
Add our Templates
template/appname/stubs/icon.html
{% load evelinks %}
{% character_portrait_url row 32 %}
template/appname/stubs/name.html
{{ row.character_name }} <span class="text-small">({{ row.character_ownership.user.username }})</span>
template/appname/stubs/corp.html
{{ row.corporation_name }}
template/appname/list.html
{% extends "allianceauth/base-bs5.html" %}
{% load i18n %}
{% block page_title %}
{% translate "App Name" %}
{% endblock page_title %}
{% block content %}
<table class="table table-striped w-100" id="table">
<!-- Normal Header Rows -->
<thead>
<tr>
<th></th>
<th>{% translate "Name" %}</th>
<th>{% translate "Corporation" %}</th>
<th>{% translate "Alliance" %}</th>
</tr>
</thead>
<!-- Put the footer in the header so it doesn't trigger the sorting on searching -->
<!-- only footers with text will get given an input -->
<!-- This is just an option, you do it however you like -->
<tfoot style="display: table-header-group;">
<tr>
<th></th>
<th>{% translate "Name" %}</th>
<th>{% translate "Corporation" %}</th>
<th>{% translate "Alliance" %}</th>
</tr>
</tfoot>
<!-- Empty tbody -->
<tbody>
</tbody>
</table>
{% endblock content %}
{% block extra_css %}
{% include 'bundles/datatables-css-bs5.html' %}
{% endblock %}
{% block extra_javascript %}
{% include 'bundles/datatables-js-bs5.html' %}
<script>
$(document).ready(function() {
$('#table').DataTable({
serverSide: true,
ajax: '{% url "appname:table" %}',
// This is for the column searching
initComplete: function () {
this.api()
.columns()
.every(function () {
let column = this;
let title = column.footer().textContent;
if (title != ""){
// Create input element
let input = document.createElement('input');
input.classList.add("w-100")
input.placeholder = title;
column.footer().replaceChildren(input);
// Event listener for user input
input.addEventListener('keyup', () => {
if (column.search() !== this.value) {
column.search(input.value).draw();
}
});
}
});
},
columnDefs: [
{ "searchable": false, "targets": [0] },
{ "sortable": false, "targets": [0] },
],
order: [
[1, "asc"]
],
pageLength: 10,
responsive : true
});
});
</script>
{% endblock extra_javascript %}
Add our Views
Then we can setup out view in our appname/views.py file.
from django.shortcuts import render
# Alliance Auth
from allianceauth.framework.datatables import DataTablesView
from allianceauth.eveonline.models import EveCharacter
## Datatables server side view
class EveCharacterTable(DataTablesView):
model = EveCharacter
# Columns are rendered from these templates
# Templates can be a html file or template language directly in the list below
templates = [
"appname/stubs/icon.html",
"appname/stubs/name.html",
"appname/stubs/corp.html",
"{{ row.alliance_name }} {{ row.alliance_id }}"
]
# Define the columns for filtering and ordering
columns = [
# (can_sort: bool, "field_for_queries_or_sort")
(False, ""),
(True, "character_name"),
(True, "corporation_name"),
(True, "alliance_name"),
]
# if you need to do some prefetch or pre-filtering you can overide this function
def get_model_qs(self, request: HttpRequest):
qs = self.model.objects
if not request.user.is_superuser:
# eg only show unlinked characters to non-superusers
# just an example
# filtering here will prevent people searching things that may not be visible to them
qs = qs.filter(character_ownership__isnull=True)
# maybe some character ownership select related for performance?
return qs.select_related("character_ownership", "character_ownership__user")
## Main Page View
def show_table(request):
return render("appname/list.html")
Add our Urls
appname/urls.py
from django.urls import path
from . import views
app_name = 'appname'
urlpatterns = [
path("list/", views.EveCharacterTable.as_view(), name='eve_character_table'),
path("tables/data_table", views.show_table, name='table')
]
and you are done.