django-advanced-datatables 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- django_advanced_datatables-1.0.0/LICENSE +21 -0
- django_advanced_datatables-1.0.0/MANIFEST.in +3 -0
- django_advanced_datatables-1.0.0/PKG-INFO +406 -0
- django_advanced_datatables-1.0.0/README.md +385 -0
- django_advanced_datatables-1.0.0/django_advanced_datatables.egg-info/PKG-INFO +406 -0
- django_advanced_datatables-1.0.0/django_advanced_datatables.egg-info/SOURCES.txt +111 -0
- django_advanced_datatables-1.0.0/django_advanced_datatables.egg-info/dependency_links.txt +1 -0
- django_advanced_datatables-1.0.0/django_advanced_datatables.egg-info/requires.txt +6 -0
- django_advanced_datatables-1.0.0/django_advanced_datatables.egg-info/top_level.txt +1 -0
- django_advanced_datatables-1.0.0/django_datatables/__init__.py +1 -0
- django_advanced_datatables-1.0.0/django_datatables/admin.py +7 -0
- django_advanced_datatables-1.0.0/django_datatables/apps.py +13 -0
- django_advanced_datatables-1.0.0/django_datatables/cache.py +69 -0
- django_advanced_datatables-1.0.0/django_datatables/colour_rows.py +1 -0
- django_advanced_datatables-1.0.0/django_datatables/column_visibility/__init__.py +0 -0
- django_advanced_datatables-1.0.0/django_datatables/column_visibility/mixins.py +86 -0
- django_advanced_datatables-1.0.0/django_datatables/column_visibility/modals.py +117 -0
- django_advanced_datatables-1.0.0/django_datatables/columns/__init__.py +11 -0
- django_advanced_datatables-1.0.0/django_datatables/columns/column_base.py +444 -0
- django_advanced_datatables-1.0.0/django_datatables/columns/columns.py +465 -0
- django_advanced_datatables-1.0.0/django_datatables/columns/currency.py +137 -0
- django_advanced_datatables-1.0.0/django_datatables/columns/date_time.py +50 -0
- django_advanced_datatables-1.0.0/django_datatables/columns/many_to_many.py +101 -0
- django_advanced_datatables-1.0.0/django_datatables/columns/modal_columns.py +108 -0
- django_advanced_datatables-1.0.0/django_datatables/constants.py +9 -0
- django_advanced_datatables-1.0.0/django_datatables/datatables/__init__.py +6 -0
- django_advanced_datatables-1.0.0/django_datatables/datatables/column_initialiser.py +104 -0
- django_advanced_datatables-1.0.0/django_datatables/datatables/datatable_error.py +2 -0
- django_advanced_datatables-1.0.0/django_datatables/datatables/datatable_table.py +508 -0
- django_advanced_datatables-1.0.0/django_datatables/datatables/server_side.py +556 -0
- django_advanced_datatables-1.0.0/django_datatables/datatables/simple_table.py +47 -0
- django_advanced_datatables-1.0.0/django_datatables/datatables/views.py +157 -0
- django_advanced_datatables-1.0.0/django_datatables/detect_device.py +5 -0
- django_advanced_datatables-1.0.0/django_datatables/downloads/__init__.py +0 -0
- django_advanced_datatables-1.0.0/django_datatables/downloads/clipboard.py +54 -0
- django_advanced_datatables-1.0.0/django_datatables/downloads/excel_download.py +113 -0
- django_advanced_datatables-1.0.0/django_datatables/filters.py +93 -0
- django_advanced_datatables-1.0.0/django_datatables/helpers.py +128 -0
- django_advanced_datatables-1.0.0/django_datatables/includes.py +60 -0
- django_advanced_datatables-1.0.0/django_datatables/migrations/0001_initial.py +28 -0
- django_advanced_datatables-1.0.0/django_datatables/migrations/0002_savedstate_column_order_savedstate_column_visibility_and_more.py +28 -0
- django_advanced_datatables-1.0.0/django_datatables/migrations/0003_alter_savedstate_state.py +18 -0
- django_advanced_datatables-1.0.0/django_datatables/migrations/0004_alter_savedstate_public_alter_savedstate_state_and_more.py +29 -0
- django_advanced_datatables-1.0.0/django_datatables/migrations/__init__.py +0 -0
- django_advanced_datatables-1.0.0/django_datatables/modal_filter/__init__.py +0 -0
- django_advanced_datatables-1.0.0/django_datatables/modal_filter/filter_fields.py +60 -0
- django_advanced_datatables-1.0.0/django_datatables/modal_filter/mixins.py +115 -0
- django_advanced_datatables-1.0.0/django_datatables/modal_filter/modals.py +42 -0
- django_advanced_datatables-1.0.0/django_datatables/modals.py +39 -0
- django_advanced_datatables-1.0.0/django_datatables/model_def.py +71 -0
- django_advanced_datatables-1.0.0/django_datatables/models.py +19 -0
- django_advanced_datatables-1.0.0/django_datatables/plugins/__init__.py +0 -0
- django_advanced_datatables-1.0.0/django_datatables/plugins/colour_rows.py +22 -0
- django_advanced_datatables-1.0.0/django_datatables/plugins/column_totals.py +58 -0
- django_advanced_datatables-1.0.0/django_datatables/plugins/reorder.py +10 -0
- django_advanced_datatables-1.0.0/django_datatables/plugins/save_filters.py +28 -0
- django_advanced_datatables-1.0.0/django_datatables/reorder_datatable.py +67 -0
- django_advanced_datatables-1.0.0/django_datatables/server_side_filters.py +401 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/css/datatables.css +247 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/datatables/css/datatables.min.css +24 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/datatables/js/datatables.min.js +375 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/js/filtered-datatable.js +1270 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/js/filtered_datatables_legacy.js +1057 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/js/runtime.js +754 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/js/spreadsheet.js +98 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/jspreadsheet/index.d.ts +3065 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/jspreadsheet/index.js +23 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/jspreadsheet/jspreadsheet.css +761 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/jspreadsheet/jspreadsheet.datatables.css +95 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/jsuites/jsuites.css +2930 -0
- django_advanced_datatables-1.0.0/django_datatables/static/django_datatables/jsuites/jsuites.js +12414 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/clear_table.html +18 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/base_filter_block.html +28 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/date_filter.html +78 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/filter_control.html +92 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/pivot_filter.html +19 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/pivot_totals.html +55 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/python_pivot_filter.html +79 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/row_tree.html +73 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/select2_filter.html +85 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/selected_filter.html +75 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/server_date_filter.html +81 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/server_pivot_filter.html +19 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/server_pivot_totals.html +44 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/server_select2_filter.html +118 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/server_tag_filter.html +159 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/table_search.html +22 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_blocks/tag_filter.html +175 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_rows/checkbox_filter.html +8 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_rows/checkbox_python.html +8 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_rows/checkbox_tag.html +9 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/filter_rows/checkbox_total.html +11 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/horizontal_table.html +32 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/icon_menu.html +14 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/no_of_results.html +15 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/no_of_rows.html +21 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/plugins/colour_rows.html +13 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/plugins/column_totals.html +91 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/plugins/reorder.html +20 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/plugins/save_state.html +97 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/search_boxes.html +63 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/spreadsheet.html +9 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/table.html +40 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/view_file_modal.html +46 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/widgets/datatable-reorder.html +24 -0
- django_advanced_datatables-1.0.0/django_datatables/templates/datatables/widgets/datatable.html +78 -0
- django_advanced_datatables-1.0.0/django_datatables/templatetags/__init__.py +0 -0
- django_advanced_datatables-1.0.0/django_datatables/templatetags/datatable_tags.py +48 -0
- django_advanced_datatables-1.0.0/django_datatables/urls.py +8 -0
- django_advanced_datatables-1.0.0/django_datatables/utils.py +11 -0
- django_advanced_datatables-1.0.0/django_datatables/widgets.py +58 -0
- django_advanced_datatables-1.0.0/pyproject.toml +32 -0
- django_advanced_datatables-1.0.0/setup.cfg +4 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2020 Ian Jones
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,406 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: django-advanced-datatables
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Django views with javascript filters using Datatables
|
|
5
|
+
Author: Ian Jones
|
|
6
|
+
Maintainer: Thomas Turner
|
|
7
|
+
License-Expression: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/django-advance-utils/django-advanced-datatables
|
|
9
|
+
Project-URL: Upstream, https://github.com/jonesim/django-datatables
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Operating System :: OS Independent
|
|
12
|
+
Requires-Python: >=3.6
|
|
13
|
+
Description-Content-Type: text/markdown
|
|
14
|
+
License-File: LICENSE
|
|
15
|
+
Requires-Dist: ajax-advanced-helpers>=1.0.1
|
|
16
|
+
Requires-Dist: django-advanced-menus>=1.0.0
|
|
17
|
+
Requires-Dist: django-advanced-modals>=1.0.0
|
|
18
|
+
Provides-Extra: excel
|
|
19
|
+
Requires-Dist: openpyxl; extra == "excel"
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
|
|
22
|
+
[](https://pypi.org/project/django-advanced-datatables/)
|
|
23
|
+
|
|
24
|
+
# django-advanced-datatables
|
|
25
|
+
|
|
26
|
+
The [django-advance-utils](https://github.com/django-advance-utils) line of Ian Jones's
|
|
27
|
+
[django-filtered-datatables](https://github.com/jonesim/django-datatables), forked so that releases can be
|
|
28
|
+
cut as the downstream libraries and django-advanced-report-builder need them. The Python package
|
|
29
|
+
is still `django_datatables`, so existing imports and `INSTALLED_APPS` entries do not change; only the
|
|
30
|
+
pip name does. It depends on [ajax-advanced-helpers](https://github.com/django-advance-utils/ajax-advanced-helpers),
|
|
31
|
+
[django-advanced-menus](https://github.com/django-advance-utils/django-advanced-menus) and
|
|
32
|
+
[django-advanced-modals](https://github.com/django-advance-utils/django-advanced-modals).
|
|
33
|
+
|
|
34
|
+
A Django library for building interactive data tables powered by [DataTables.js](https://datatables.net/), with server-side processing, dynamic JavaScript filters, inline editing, and a rich plugin system.
|
|
35
|
+
|
|
36
|
+
Define your tables in Python using Django models and ORM queries -- columns, filters, sorting, annotations, and rendering are all configured from your views, with minimal JavaScript required.
|
|
37
|
+
|
|
38
|
+
## Features
|
|
39
|
+
|
|
40
|
+
- **20+ column types** -- dates, currency, booleans, links, many-to-many, choice fields, lambdas, and more
|
|
41
|
+
- **AJAX and non-AJAX modes** -- load data dynamically or render inline
|
|
42
|
+
- **JavaScript filters** -- pivot, tag, select2, date range, and text search filters
|
|
43
|
+
- **Modal filter dialogs** -- form-based filtering with crispy-forms support
|
|
44
|
+
- **Inline editing** -- edit cells directly in the table with select2 dropdowns or text inputs
|
|
45
|
+
- **Row selection** -- checkbox-based row selection with bulk actions
|
|
46
|
+
- **Plugins** -- column totals, conditional row colouring, drag-and-drop reordering, save/restore filter state
|
|
47
|
+
- **Data export** -- Excel (.xlsx) download and clipboard copy
|
|
48
|
+
- **Client-side rendering** -- render functions for badges, links, conditional formatting, and lookups
|
|
49
|
+
- **Django ORM integration** -- annotations, aggregations, foreign key traversal, callable model methods
|
|
50
|
+
- **Model-defined columns** -- configure columns directly on your Django models via an inner `Datatable` class
|
|
51
|
+
- **Multiple tables per view** -- display several tables on a single page
|
|
52
|
+
- **Spreadsheet mode** -- JSpreadsheet integration for spreadsheet-like editing
|
|
53
|
+
- **Form widgets** -- `DataTableWidget` and `DataTableReorderWidget` for use in Django forms
|
|
54
|
+
- **Mobile responsive** -- automatic device detection with per-device column visibility
|
|
55
|
+
- **Redis caching** -- optional cache layer with signal-based invalidation
|
|
56
|
+
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install django-advanced-datatables
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
Add to your `INSTALLED_APPS`:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
INSTALLED_APPS = [
|
|
67
|
+
# ...
|
|
68
|
+
'django_datatables',
|
|
69
|
+
'ajax_helpers',
|
|
70
|
+
# ...
|
|
71
|
+
]
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Include the required JavaScript and CSS in your base template. The library depends on DataTables.js, jQuery, and Bootstrap.
|
|
75
|
+
|
|
76
|
+
## Quick Start
|
|
77
|
+
|
|
78
|
+
### 1. Define a view
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
from django_datatables.datatables import DatatableView
|
|
82
|
+
|
|
83
|
+
class CompanyList(DatatableView):
|
|
84
|
+
model = Company
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def setup_table(table):
|
|
88
|
+
table.add_columns(
|
|
89
|
+
'id',
|
|
90
|
+
'name',
|
|
91
|
+
'dissolved',
|
|
92
|
+
)
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 2. Wire up the URL
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
urlpatterns = [
|
|
99
|
+
path('companies/', CompanyList.as_view(), name='company-list'),
|
|
100
|
+
]
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### 3. Use the template
|
|
104
|
+
|
|
105
|
+
The default template renders a complete DataTables table. You can override it via `template_name` on your view.
|
|
106
|
+
|
|
107
|
+
## Usage
|
|
108
|
+
|
|
109
|
+
### Adding Columns
|
|
110
|
+
|
|
111
|
+
Columns can be added in several ways:
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
def setup_table(table):
|
|
115
|
+
table.add_columns(
|
|
116
|
+
'name', # model field name
|
|
117
|
+
('id', {'title': 'ID', 'width': '30px'}), # tuple with options
|
|
118
|
+
DateColumn('date_entered', column_name='Date'), # column class instance
|
|
119
|
+
'company__name', # foreign key traversal
|
|
120
|
+
'Tags', # model-defined column
|
|
121
|
+
)
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**String prefix syntax** for quick column options:
|
|
125
|
+
- `.field` -- hidden column (still available for filtering/rendering)
|
|
126
|
+
- `_field` -- calculated column (not from the database)
|
|
127
|
+
- `$field` -- secure column (hidden from client source)
|
|
128
|
+
|
|
129
|
+
### Column Types
|
|
130
|
+
|
|
131
|
+
| Column | Purpose |
|
|
132
|
+
|--------|---------|
|
|
133
|
+
| `DatatableColumn` | Standard column with customisable `row_result` and `col_setup` |
|
|
134
|
+
| `DateColumn` | Formats dates (dd/mm/yyyy) |
|
|
135
|
+
| `DateTimeColumn` | Formats datetimes |
|
|
136
|
+
| `ChoiceColumn` | Maps integer choices to display labels |
|
|
137
|
+
| `CurrencyColumn` | Currency formatting |
|
|
138
|
+
| `BooleanColumn` | Boolean display |
|
|
139
|
+
| `ColumnLink` | Clickable link using Django URL names |
|
|
140
|
+
| `ManyToManyColumn` | Displays many-to-many relationships |
|
|
141
|
+
| `CallableColumn` | Calls a model method |
|
|
142
|
+
| `LambdaColumn` | Processes values with a lambda function |
|
|
143
|
+
| `SelectColumn` | Row selection checkboxes |
|
|
144
|
+
| `TextFieldColumn` | Long text with truncation |
|
|
145
|
+
|
|
146
|
+
### Model-Defined Columns
|
|
147
|
+
|
|
148
|
+
Configure columns directly on your models:
|
|
149
|
+
|
|
150
|
+
```python
|
|
151
|
+
class Company(models.Model):
|
|
152
|
+
name = models.CharField(max_length=80)
|
|
153
|
+
|
|
154
|
+
class Datatable(DatatableModel):
|
|
155
|
+
# Annotation-based column
|
|
156
|
+
people = {'annotations': {'people': Count('person__id')}}
|
|
157
|
+
|
|
158
|
+
# Link column
|
|
159
|
+
collink_1 = ColumnLink(title='View', field=['id', 'name'], url_name='company-detail')
|
|
160
|
+
|
|
161
|
+
# Column list (renders multiple fields as a group)
|
|
162
|
+
company_list = ['id', 'name']
|
|
163
|
+
|
|
164
|
+
# Custom column class
|
|
165
|
+
class ModelIdColumn(DatatableColumn):
|
|
166
|
+
def col_setup(self):
|
|
167
|
+
self.field = 'id'
|
|
168
|
+
self.title = 'Custom ID'
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
These columns can then be referenced by name in `add_columns()`:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
table.add_columns('id', 'name', 'people', 'collink_1', 'ModelIdColumn')
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Filters
|
|
178
|
+
|
|
179
|
+
```python
|
|
180
|
+
def setup_table(table):
|
|
181
|
+
table.add_columns('id', 'name', 'company__name', 'Tags')
|
|
182
|
+
|
|
183
|
+
# JavaScript filters
|
|
184
|
+
table.add_js_filters('tag', 'Tags') # tag filter
|
|
185
|
+
table.add_js_filters('select2', 'company__name') # select2 dropdown
|
|
186
|
+
table.add_js_filters('totals', 'id') # totals/count filter
|
|
187
|
+
table.add_js_filters('date', 'date_entered') # date range
|
|
188
|
+
table.add_js_filters('expand', 'level', id_column='id') # tree expand
|
|
189
|
+
|
|
190
|
+
# ORM-level filters
|
|
191
|
+
table.filter = {'company__id': 1}
|
|
192
|
+
table.exclude = {'dissolved': True}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
#### Modal Filter (form-based)
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
from django_datatables.modal_filter.mixins import DatatableFilterMixin, DatatableFilterField
|
|
199
|
+
|
|
200
|
+
class CompanyList(DatatableFilterMixin, DatatableView):
|
|
201
|
+
model = Company
|
|
202
|
+
filter_fields = [
|
|
203
|
+
DatatableFilterField('Company Name', CharField(required=False), datatable_field='name__contains'),
|
|
204
|
+
DatatableFilterField('Tags', FilterModelMultipleChoiceField(queryset=Tags.objects.all()), datatable_field='tags__in'),
|
|
205
|
+
]
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Sorting
|
|
209
|
+
|
|
210
|
+
```python
|
|
211
|
+
table.sort('name') # ascending
|
|
212
|
+
table.sort('-name') # descending
|
|
213
|
+
table.sort('name', '-id') # multi-column
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Column Search
|
|
217
|
+
|
|
218
|
+
Per-column search boxes appear below the header by default. Customise them:
|
|
219
|
+
|
|
220
|
+
```python
|
|
221
|
+
table.add_columns(
|
|
222
|
+
ColumnBase(column_name='status', field='dissolved',
|
|
223
|
+
col_search_select=[['true', 'Dissolved'], ['false', 'Active']]),
|
|
224
|
+
ColumnBase(column_name='order', field='order', no_col_search=True),
|
|
225
|
+
)
|
|
226
|
+
table.table_options['no_col_search'] = True # disable all column search
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### Client-Side Rendering
|
|
230
|
+
|
|
231
|
+
Render functions transform cell data in the browser without extra server round-trips:
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
from django_datatables.helpers import render_replace, row_button
|
|
235
|
+
|
|
236
|
+
table.add_columns(
|
|
237
|
+
# Badge rendering
|
|
238
|
+
ColumnBase(column_name='people', field='people', render=[
|
|
239
|
+
render_replace(column='people', html='<span class="badge badge-primary">%1%</span>'),
|
|
240
|
+
]),
|
|
241
|
+
|
|
242
|
+
# Row action button
|
|
243
|
+
ColumnBase(column_name='action', render=[row_button('delete', 'Delete')]),
|
|
244
|
+
|
|
245
|
+
# Lookup-based rendering
|
|
246
|
+
('id', {'title': 'Status', 'render': [
|
|
247
|
+
{'function': 'ReplaceLookup', 'html': '%1%', 'var': '%1%'}
|
|
248
|
+
], 'lookup': [[1, 'Active'], [2, 'Inactive']]}),
|
|
249
|
+
)
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Available render functions: `Replace`, `ReplaceLookup`, `Html`, `MergeArray`, `ValueInColumn`.
|
|
253
|
+
|
|
254
|
+
### Plugins
|
|
255
|
+
|
|
256
|
+
```python
|
|
257
|
+
from django_datatables.plugins.colour_rows import ColourRows
|
|
258
|
+
from django_datatables.plugins.column_totals import ColumnTotals
|
|
259
|
+
from django_datatables.plugins.reorder import Reorder
|
|
260
|
+
|
|
261
|
+
# Conditional row colouring
|
|
262
|
+
table.add_plugin(ColourRows, [
|
|
263
|
+
{'column': 'status', 'values': {'overdue': 'table-danger', 'pending': 'table-warning'}}
|
|
264
|
+
])
|
|
265
|
+
|
|
266
|
+
# Column totals in footer
|
|
267
|
+
table.add_plugin(ColumnTotals, {
|
|
268
|
+
'amount': {'sum': True},
|
|
269
|
+
'id': {'text': 'Total', 'css_class': 'text-danger'},
|
|
270
|
+
'percentage': {'sum': 'percentage', 'numerator': 'vans', 'denominator': 'total', 'decimal_places': 1},
|
|
271
|
+
})
|
|
272
|
+
|
|
273
|
+
# Drag-and-drop row reordering
|
|
274
|
+
table.add_plugin(Reorder)
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
### Inline Editing
|
|
278
|
+
|
|
279
|
+
```python
|
|
280
|
+
def setup_table(table):
|
|
281
|
+
table.edit_fields = ['first_name', 'title']
|
|
282
|
+
table.edit_options = {'company__name': {'select2': True}}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Row Actions (AJAX Commands)
|
|
286
|
+
|
|
287
|
+
Handle row-level actions from buttons:
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
class MyView(DatatableView):
|
|
291
|
+
ajax_commands = ['row']
|
|
292
|
+
|
|
293
|
+
def row_delete(self, **kwargs):
|
|
294
|
+
return self.command_response('delete_row', row_no=kwargs['row_no'], table_id=kwargs['table_id'])
|
|
295
|
+
|
|
296
|
+
def row_toggle_tag(self, **kwargs):
|
|
297
|
+
row_data = json.loads(kwargs['row_data'])
|
|
298
|
+
# ... process action ...
|
|
299
|
+
table = self.tables[kwargs['table_id']]
|
|
300
|
+
return table.refresh_row(self.request, kwargs['row_no'])
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Data Export
|
|
304
|
+
|
|
305
|
+
```python
|
|
306
|
+
from django_datatables.downloads.excel_download import ExcelDownload
|
|
307
|
+
from django_datatables.downloads.clipboard import ClipboardCopy
|
|
308
|
+
|
|
309
|
+
class MyView(ExcelDownload, ClipboardCopy, DatatableView):
|
|
310
|
+
model = MyModel
|
|
311
|
+
|
|
312
|
+
def setup_menu(self):
|
|
313
|
+
self.add_menu('menu', 'buttons').add_items(
|
|
314
|
+
self.download_menu_item(),
|
|
315
|
+
self.clipboard_menu_item(),
|
|
316
|
+
)
|
|
317
|
+
super().setup_menu()
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
### Multiple Tables Per View
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
class TwoTableView(DatatableView):
|
|
324
|
+
template_name = 'two_tables.html'
|
|
325
|
+
|
|
326
|
+
def add_tables(self):
|
|
327
|
+
self.add_table('t1', model=Company)
|
|
328
|
+
self.add_table('t2', model=Person)
|
|
329
|
+
|
|
330
|
+
@staticmethod
|
|
331
|
+
def setup_t1(table):
|
|
332
|
+
table.add_columns('id', 'name')
|
|
333
|
+
|
|
334
|
+
@staticmethod
|
|
335
|
+
def setup_t2(table):
|
|
336
|
+
table.add_columns('id', 'first_name')
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Non-Model Data
|
|
340
|
+
|
|
341
|
+
Load data from any source (JSON files, APIs, etc.):
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
class JsonTableView(DatatableView):
|
|
345
|
+
|
|
346
|
+
@staticmethod
|
|
347
|
+
def setup_table(table):
|
|
348
|
+
table.add_columns(
|
|
349
|
+
ColumnBase(column_name='field1'),
|
|
350
|
+
ColumnBase(column_name='field2'),
|
|
351
|
+
)
|
|
352
|
+
|
|
353
|
+
@staticmethod
|
|
354
|
+
def get_table_query(table, **kwargs):
|
|
355
|
+
with open('data.json') as f:
|
|
356
|
+
return json.load(f)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
### Custom Column Classes
|
|
360
|
+
|
|
361
|
+
```python
|
|
362
|
+
from django_datatables.columns import DatatableColumn
|
|
363
|
+
|
|
364
|
+
class FullName(DatatableColumn):
|
|
365
|
+
def col_setup(self):
|
|
366
|
+
self.field = ['first_name', 'surname']
|
|
367
|
+
|
|
368
|
+
def row_result(self, data_dict, _page_results):
|
|
369
|
+
return f'{data_dict["first_name"]} {data_dict["surname"]}'
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Table Options
|
|
373
|
+
|
|
374
|
+
Common options passed via `table.table_options`:
|
|
375
|
+
|
|
376
|
+
```python
|
|
377
|
+
table.table_options['pageLength'] = 50
|
|
378
|
+
table.table_options['no_col_search'] = True
|
|
379
|
+
table.table_options['scrollX'] = True
|
|
380
|
+
table.table_options['ajax_url'] = '/custom/ajax/url/'
|
|
381
|
+
table.table_options['row_href'] = [render_replace(column='id', html='/detail/%1%/')]
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
## Demo Application
|
|
385
|
+
|
|
386
|
+
A Docker-based demo is included with sample data and 15+ examples covering filters, plugins, editing, rendering, and more.
|
|
387
|
+
|
|
388
|
+
```bash
|
|
389
|
+
docker-compose up
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Then visit [http://localhost:8006](http://localhost:8006).
|
|
393
|
+
|
|
394
|
+
## Dependencies
|
|
395
|
+
|
|
396
|
+
- Python >= 3.6
|
|
397
|
+
- Django
|
|
398
|
+
- [ajax-advanced-helpers](https://github.com/django-advance-utils/ajax-advanced-helpers) >= 1.0.1
|
|
399
|
+
|
|
400
|
+
Optional:
|
|
401
|
+
- `openpyxl` -- for Excel export
|
|
402
|
+
- `redis` -- for table caching
|
|
403
|
+
|
|
404
|
+
## License
|
|
405
|
+
|
|
406
|
+
MIT
|