mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-03 21:56:20 +01:00
7.3 KiB
7.3 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 %}
{% load aa_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>
</table>
{% endblock content %}
{% block extra_css %}
{% include "bundles/datatables-2-css-bs5.html" %}
{% comment %} If you don't use the ColumnControl Extension, remove the next line {% endcomment %}
{% include "bundles/datatables-2-columncontrol-css-bs5.html" %}
{% endblock %}
{% block extra_javascript %}
{% get_datatables_language_static LANGUAGE_CODE as DT_LANG_PATH %}
{% include "bundles/datatables-2-js-bs5.html" %}
{% comment %} If you don't use the ColumnControl Extension, remove the next line {% endcomment %}
{% include "bundles/datatables-2-columncontrol-js-bs5.html" %}
<script>
$(document).ready(() => {
// Assuming you have a table with the ID 'table'
// A jQuery HTML Element `$('#table')` can also be passed instead of a selector string
const dt = new DataTable('#table', {
language: {
url: '{{ DT_LANG_PATH }}',
// Important: The value for `language.processing` must be passed
// as a JS template string, not as a normal string. This is to
// allow for Django template rendering inside the processing
// indicator.
processing: `{% include "framework/datatables/process-indicator.html" %}`
},
layout: { // See: https://datatables.net/reference/option/layout
topStart: 'pageLength',
topEnd: 'search',
bottomStart: 'info',
bottomEnd: 'paging'
},
ordering: { // See: https://datatables.net/reference/option/ordering
handler: true, // Enable ordering by clicking on column headers
indicators: false, // Disable ordering indicators on column headers (important when ColumnControl is used)
},
processing: true, // Show processing indicator when loading data
serverSide: true, // Enable server-side processing
ajax: '{% url "appname:data_table_view" %}',
columnDefs: [
{
targets: [0],
columnControl: [],
sortable: false,
searchable: false
},
{
targets: [1,2,3],
columnControl: [
{
target: 0,
content: []
},
{
target: 1,
content: ['search']
}
],
}
],
order: [
[1, "asc"]
],
pageLength: 10, // Override default page length if desired
responsive : true
});
});
</script>
{% endblock extra_javascript %}
Add our Views
Then we can setup out view in our appname/views.py file.
Columns definition
The columns must be defined as a 2 part tuple
- Part 1 is the database field that will be used for filtering and ordering. If this is a foreign key you need to point to a field that is compatible with
__icontainslikecharFieldortextField. It can beNone/False/""if no ordering for filtering is required for this row.- Examples for the EveCharacter Model:
character_namecharacter_ownership__user__usernamecharacter_ownership__user__profile__main_character__character_name
- Examples for the EveCharacter Model:
- Part 2 is a string that is used to the render the column for each row. This can be a html stub or a string containing django style template language.
- Examples for the EveCharacter Model
{{ row.character_name }}{{ row.character_ownership.user.username }}{{ row.character_ownership.user.profile.main_character.character_name }}appname/stubs/character_img.html
- Examples for the EveCharacter Model
appname/views.py
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
# Define the columns as a tuple.
# String for field name for filtering and ordering
# String for the render template
# Templates can be a html file or template language directly in the list below
columns = [
# ("field_for_queries_or_sort", template: str)
("", "appname/stubs/icon.html"),
("character_name", "appname/stubs/name.html"),
("corporation_name", "appname/stubs/corp.html"),
("alliance_name", "{{ row.alliance_name }} {{ row.alliance_id }}"),
]
# 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='data_table_view')
]
and you are done.