mirror of
https://gitlab.com/allianceauth/allianceauth.git
synced 2026-02-04 06:06:19 +01:00
[Feature] Basic framework for datatables server rendering
This commit is contained in:
181
docs/development/custom/framework/datatables.md
Normal file
181
docs/development/custom/framework/datatables.md
Normal file
@@ -0,0 +1,181 @@
|
||||
# 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
|
||||
|
||||
```django
|
||||
{% load evelinks %}
|
||||
{% character_portrait_url row 32 %}
|
||||
```
|
||||
|
||||
### template/appname/stubs/name.html
|
||||
|
||||
```django
|
||||
{{ row.character_name }} <span class="text-small">({{ row.character_ownership.user.username }})</span>
|
||||
```
|
||||
|
||||
### template/appname/stubs/corp.html
|
||||
|
||||
```django
|
||||
{{ row.corporation_name }}
|
||||
```
|
||||
|
||||
### template/appname/list.html
|
||||
|
||||
```django
|
||||
{% 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>
|
||||
</table>
|
||||
{% endblock content %}
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="https://cdn.datatables.net/2.3.6/css/dataTables.bootstrap5.css" />
|
||||
<link href="https://cdn.datatables.net/columncontrol/1.2.0/css/columnControl.bootstrap5.min.css" rel="stylesheet">
|
||||
{% endblock %}
|
||||
{% block extra_javascript %}
|
||||
<script src="https://cdn.datatables.net/2.3.6/js/dataTables.js"></script>
|
||||
<script src="https://cdn.datatables.net/2.3.6/js/dataTables.bootstrap5.js"></script>
|
||||
<script src="https://cdn.datatables.net/columncontrol/1.2.0/js/dataTables.columnControl.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#table').DataTable({
|
||||
serverSide: true,
|
||||
ajax: '{% url "appname:table" %}',
|
||||
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,
|
||||
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 `__icontains` like `charField` or `textField`. It can be `None`/`False`/`""` if no ordering for filtering is required for this row.
|
||||
- Examples for the EveCharacter Model:
|
||||
- `character_name`
|
||||
- `character_ownership__user__username`
|
||||
- `character_ownership__user__profile__main_character__character_name`
|
||||
- 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`
|
||||
|
||||
### appname/views.py
|
||||
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
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.
|
||||
Reference in New Issue
Block a user