Giter Site home page Giter Site logo

morlandi / django-ajax-datatable Goto Github PK

View Code? Open in Web Editor NEW
204.0 204.0 64.0 2.27 MB

A Django app which provides the integration of a Django project with the jQuery Javascript library DataTables.net

License: MIT License

Python 72.92% CSS 2.49% JavaScript 12.13% HTML 12.47%

django-ajax-datatable's People

Contributors

ivi3 avatar klavman avatar maps82 avatar mike3285 avatar morlandi avatar petrdlouhy avatar shuki25 avatar tboulogne avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

django-ajax-datatable's Issues

AssertionError: No exception message supplied

Hello,

I've done everything from readme to build a basic setup but I get the following error:

AssertionError at /denuncia/report_search/
No exception message supplied

Request Method: GET
http://localhost:8000/denuncia/report_search/
3.0.7
AssertionError
/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/ajax_datatable/views.py in dispatch, line 383
/Users/keniobats/.pyenv/versions/bigeye/bin/python
3.7.4
['/Users/keniobats/Dev/bigeye', '/Users/keniobats/.pyenv/versions/3.7.4/lib/python37.zip', '/Users/keniobats/.pyenv/versions/3.7.4/lib/python3.7', '/Users/keniobats/.pyenv/versions/3.7.4/lib/python3.7/lib-dynload', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/odf', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/odf', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/odf', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/odf', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/odf', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/odf', '/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/odf'

/Users/keniobats/.pyenv/versions/bigeye/lib/python3.7/site-packages/ajax_datatable/views.py in dispatch

                return JsonResponse({
                    'html': self.render_row_details(row_id, request),
                    'parent-row-id': row_id,
                })
            response = super(AjaxDatatableView, self).dispatch(request, *args, **kwargs)
        else:
            assert False
            #response = HttpResponse(self.render_table(request))
        return response
    def get_model_admin(self):
        from django.contrib import admin
        if self.model in admin.site._registry:

Variable Value
class <class 'ajax_datatable.views.AjaxDatatableView'>
args ()
kwargs {}
request <WSGIRequest: GET '/denuncia/report_search/'>
self <whistleblower.datatables_views.RegisterAjaxDatatableView object at 0x10f5c7f10>

I have been trying to get around this with no success so any help will be extremely appreciated!
Django version: 3.0.7
Python version: 3.7.4

AssertError

I tried to use the package bu I got the issue: AssertError

get_template_name : doc out of date or regression ?

Hello,

Did not find anymore get_template_name in code, overriding have no effect.
And template_name value too.

Did you remove this feature (and keep it in doc ?) or a badly regression ?

Thanks for answer (and for this great works :-) ).

Regards

Border : 1px added in div in when 'searchable': False

Hi,

I have a column_defs with first column a button to Edit.
This column is not searchable or order-able. So on top there should not be such elements

However there is a styling added to the div that will reassemble like this s an searchable filed but in fact this is a border.

class CustomerAjaxDatatableView(AjaxDatatableView):

    model = Customer
    title = 'Customer'
    initial_order = [["name", "asc"], ]
    length_menu = [[10, 20, 50, 100, -1], [10, 20, 50, 100, 'all']]
    search_values_separator = '+'

    column_defs = [
        {'name': 'edit', 'title': '', 'searchable': False, 'orderable': False, },
        {'name': 'name', 'visible': True, },
        {'name': 'address1', 'visible': True, },
        {'name': 'address2', 'visible': True, },
        {'name': 'postciode', 'visible': True, },
        {'name': 'city', 'visible': True, },
        {'name': 'country', 'visible': True, },
    ]

Selection_094

Single view for ajax and template render views

Hi @morlandi
Thanks for the perfect project, I found it extremely useful (I just migrated from the pivotal datatables module).
I found it a bit strange, why we need to create two views (along with two URLs) for the single table. One view for the ajax requests and a second one for the template rendering?
I'm a bit edited source code to inherit AjaxDatatableView from the TemplateView instead View and separate ajax requests from the plain GET's to render template on GET requests and it seems working great.
Do you think it is a good idea to submit PR with these changes?

Update: I realized that fact it is ideologically incompatible with the multiple tables on the single page but for general purposes (one table per page), it can be useful. It could be something like SingleAjaxDatatableTemplateView inherited from the AjaxDatatableView or so.

request.is_ajax() is returning false

I have followed the steps and trying to use the plugin in a simple way, but I am getting an assertion error. I have looked views.py line number 381, request.is_ajax()

Reload table with new data

Hi Morlandi,
Thanks for your good library, I was able to initialize my table with some extra data in 'initialize_table' function. now I'm looking for a method to reinitialize or reload the table with a bunch of new extra data. is there any way? I tried a few methods with table.ajax.reload() but they produced confusing errors.

any help is appreciated.

issue with CSRF token

i am using Django with the
but i am always getting this error Forbidden (CSRF token missing or incorrect.)

i have tried to include the token within the AjaxDatatableViewUtils.initialize_table but not failed to do so
can you please advice
i am using the below script

<script language="javascript">

    $( document ).ready(function() {
    var crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
        AjaxDatatableViewUtils.initialize_table(
            $('#datatable-customer'),
            "{% url 'crm:ajax_datatable_customer' %}",
            {
                // extra_options (example)
                processing: false,
                autoWidth: false,
                full_row_select: false,
                scrollX: false
            }, {
                // extra_data
                // ...
            },
        );
    });

</script>

How to ise Tailwindcss classes

I ve tried to apply tailwindcss classes using tailwind's customised stylesheet. The classes get picked up in the markup but are not applied. They are being overridden by other styles. Perhaps datatables stylesheet. I ve tried moving the tailwind inclusion in the base template to after the datatable css but it does not work. Can you help me please?

You shouldn't do this in the class declaration:

You shouldn't do this in the class declaration:

Rec_Count = model.objects.all().count()
if Rec_Count > 500:
    length_menu = [[10, 25, 50, 100], [10, 25, 50, 100]]
else:
    length_menu = [[10, 25, 50, 100, -1], [10, 25, 50, 100, _("All")]]

since RecCount would be evaluated only once when the file is imported.
I would rather override get_length_menu as follows:

def get_length_menu(self):
    Rec_Count = model.objects.all().count()
    if Rec_Count > 500:
        length_menu = [[10, 25, 50, 100], [10, 25, 50, 100]]
    else:
        length_menu = [[10, 25, 50, 100, -1], [10, 25, 50, 100, _("All")]]
    return self.length_menu

Did you encounter other problems?

Originally posted by @morlandi in #11 (comment)

Support for Django 4.0

Currently, this happens when using it in a project with Django 4.0a1

  File "/Users/fraimondo/anaconda3/envs/microbiom/lib/python3.9/site-packages/ajax_datatable/columns.py", line 2, in <module>
    from django.utils.translation import ugettext_lazy as _
ImportError: cannot import name 'ugettext_lazy' from 'django.utils.translation' (/Users/fraimondo/anaconda3/envs/microbiom/lib/python3.9/site-packages/django/utils/translation/__init__.py)

This is because these functions where deprecated in Django 3.0:

https://docs.djangoproject.com/en/dev/releases/3.0/#deprecated-features-3-0

I guess it's just a matter of removing the u

Edit cell

Hi @morlandi !

I am trying to allow users to click on a cell, modify a cell and send back to django the new value.
I tried using this tutorial but I haven't achieved my goal.

Do you know how I can could do such a thing ?

Thanks a lot :)

Clarification regarding the date-range search function

I tried to implement date range on my app but it does not work, always "No data in table". Does it needs to have specific date format? (YYYY-MM-DD HH:mm:SS)? From what I understand, all you need is to provide column data with date on it (latest_by = "date_time").

Thank You for this project.

Adding raw SQL support?

Would it be possible to add support for RawQuerySet data type if we use raw SQL instead of Django's OMS? For example Manager.objects.raw_as_qs("select * from mytable")? My project has complex SQL statements for report generation and would like to be able to use raw SQL.

For example, code snippet below:

from django.db import connection
from django.db.models import Manager, Model
from ajax_datatable.views import AjaxDatatableView

class MyManager(Manager):
    def raw_as_qs(self, raw_query, params=()):
        """Execute a raw query and return a QuerySet.  The first column in the
        result set must be the id field for the model.
        :type raw_query: str | unicode
        :type params: tuple[T] | dict[str | unicode, T]
        :rtype: django.db.models.query.QuerySet
        """
        cursor = connection.cursor()
        try:
            cursor.execute(raw_query, params)
            return self.filter(id__in=(x[0] for x in cursor))
        finally:
            cursor.close()


class RawModel(Model):
    objects = MyManager()

And for the ajax call:

class AjaxJournalLog(AjaxDatatableView):
    model = RawModel
    title = "Journal Log"
    initial_order = [["game_start", "asc"]]
    length_menu = [[10, 20, 50, 100], [10, 20, 50, 100]]
    search_values_separator = "+"

    column_defs = [
        AjaxDatatableView.render_row_tools_column_def(),
        {"name": "id", "visible": False},
        {"name": "file", "visible": True},
        {"name": "game_start", "visible": True},
        {"name": "game_end", "visible": True},
        {"name": "progress_code", "visible": True},
        {"name": "rows_processed", "visible": True},
        {"name": "parser_time", "visible": True},
    ]

    def get_initial_queryset(self, request=None):
        return RawModel.objects.raw_as_qs("select * from journal_log")

Here's the traceback:

Traceback (most recent call last):
  File "/venv/lib/python3.8/site-packages/asgiref/sync.py", line 458, in thread_handler
    raise exc_info[1]
  File "/venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 38, in inner
    response = await get_response(request)
  File "/venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 233, in _get_response_async
    response = await wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/venv/lib/python3.8/site-packages/asgiref/sync.py", line 423, in __call__
    ret = await asyncio.wait_for(future, timeout=None)
  File "/Users/josh/opt/anaconda3/lib/python3.8/asyncio/tasks.py", line 455, in wait_for
    return await fut
  File "/venv/lib/python3.8/site-packages/asgiref/current_thread_executor.py", line 22, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/venv/lib/python3.8/site-packages/asgiref/sync.py", line 462, in thread_handler
    return func(*args, **kwargs)
  File "/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 70, in view
    return self.dispatch(request, *args, **kwargs)
  File "/venv/lib/python3.8/site-packages/django/utils/decorators.py", line 43, in _wrapper
    return bound_method(*args, **kwargs)
  File "/venv/lib/python3.8/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
  File "/venv/lib/python3.8/site-packages/ajax_datatable/views.py", line 405, in dispatch
    response = super(AjaxDatatableView, self).dispatch(request, *args, **kwargs)
  File "/venv/lib/python3.8/site-packages/django/views/generic/base.py", line 98, in dispatch
    return handler(request, *args, **kwargs)
  File "/venv/lib/python3.8/site-packages/ajax_datatable/views.py", line 491, in post
    return self.get(request, *args, **kwargs)
  File "/venv/lib/python3.8/site-packages/ajax_datatable/views.py", line 520, in get
    qs = self.prepare_queryset(params, qs)
  File "/venv/lib/python3.8/site-packages/ajax_datatable/views.py", line 770, in prepare_queryset
    qs = self.sort_queryset(params, qs)
  File "/venv/lib/python3.8/site-packages/ajax_datatable/views.py", line 788, in sort_queryset
    qs = qs.order_by(
  File "/venv/lib/python3.8/site-packages/django/db/models/query.py", line 1149, in order_by
    obj.query.add_ordering(*field_names)
  File "/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1991, in add_ordering
    self.names_to_path(item.split(LOOKUP_SEP), self.model._meta)
  File "/venv/lib/python3.8/site-packages/django/db/models/sql/query.py", line 1537, in names_to_path
    raise FieldError("Cannot resolve keyword '%s' into field. "
django.core.exceptions.FieldError: Cannot resolve keyword 'game_start' into field. Choices are: id

I don't think it would work well when converting RawQuerySet to QuerySet, it just introduces new problems. I'm thinking we may have to create a separate class to deal with raw SQL. I like your package and would love to use it with raw SQL as well.

I could make a PR to support that if you could direct me to the best starting point.

Cheers,
Josh

filter display issue on small screens

Hi again,

First i would like to thank you for this very useful and fast library.

one more issue i would like to report:

When i set the responsive option to true under the table options, on small devices some fields will be shown under the plus sign which is normal but the filter for those fields remain appearing on the table header which i think is better to hide

Thanks again

Column Visibility Bug

I found some weird things when I implement the 'colvis' function (column visibility) to the buttons. When I click on one of the columns in the column menu to hide, the selected column data is successfully hidden, however, the column headers are still there and even duplicated.

Screen Shot 2021-07-06 at 11 03 07

How to apply filtering for model dynamic field

I have dynamic field name, constructed based on combination for two or more model field values.
Now if I want to apply filter on this field, is it possible to apply by passing any column def argument like lookup_field or any other.

I want to pass search value = model.filed1 or model.filed2 or model.field3

XSS Vulnerability: HTML Code in field values is being executed by the datatable

If some HTML code is put in a model that is going to be rendered into a datatable with this plugin, any HTML code typed into a field of that instance will be executed and rendered by the AJAX datatable, including <script> tags.
This can lead to severe vulnerabilities.

Proof:
My datatable (all settings are default)
immagine
Adding a model with HTML in its name:
immagine
Result:
immagine

I think this behavior should absolutely be prevented by the default settings.

My initialization:

..........
    <div class="row">
        <div class="col-12">
            <div class="card">
                <div class="card-body">
                    <div class="table-responsive">
                        <table id="datatable_items" class="table align-items-center nowrap">
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>
.......
    <script>
        $(document).ready(function () {
            AjaxDatatableViewUtils.initialize_table(
                $('#datatable_items'),
                "{% url "warehouseDatatable" %}",
                {
                    // extra_options (example)
                    processing: true,
                    autoWidth: false,
                    full_row_select: true,
                    scrollX: false,
                    dom: '<"cont-sup"Bfl>rt<"cont-inf"ip>',
                    buttons: [
                        {extend: "copy", text: "Copia", className: "badge badge-primary text-sm"},
                        {extend: "csv", text: "Scarica .CSV", className: "badge badge-primary text-sm"},
                        {extend: "excel", text: "Scarica Excel", className: "badge badge-primary text-sm"},
                        {extend: "print", text: "Stampa", className: "badge badge-primary text-sm"},
                        {extend: "pdfHtml5", text: "Esporta PDF", className: "badge badge-primary text-sm"},
                    ],
                    search_icon_html: '<i class="fa fa-search" style="font-size: 16px"></i>',
                    language: {
                        "decimal": "",
                        "emptyTable": "Nessun dato disponibile",
                        "info": "Visualizzate da _START_ a _END_ di _TOTAL_ righe",
                        "infoEmpty": "",
                        "infoFiltered": "(filtered from _MAX_ total entries)",
                        "infoPostFix": "",
                        "thousands": ",",
                        "lengthMenu": "Visualizza _MENU_ righe per pagina",
                        "loadingRecords": "Caricamento...",
                        "processing": "Caricamento...",
                        "search": "",
                        "zeroRecords": "Nessun record trovato",
                        "paginate": {
                            "first": "Prima",
                            "last": "Ultima",
                            "next": ">>",
                            "previous": "<<"
                        },
                        "aria": {
                            "sortAscending": ": activate to sort column ascending",
                            "sortDescending": ": activate to sort column descending"
                        }
                    }
                },
            );
        });

    </script>

my settings.py:

##### ajax dt

AJAX_DATATABLE_MAX_COLUMNS = 30
AJAX_DATATABLE_TRACE_COLUMNDEFS = False  # enables debug tracing of applied column defs
AJAX_DATATABLE_TRACE_QUERYDICT = False  # enables debug tracing of datatables requests
AJAX_DATATABLE_TRACE_QUERYSET = False  # enables debug tracing of applied query
AJAX_DATATABLE_TEST_FILTERS = False  # trace results for each individual filter, for debugging purposes
AJAX_DATATABLE_DISABLE_QUERYSET_OPTIMIZATION = False  # all queryset optimizations are disabled

my view:

class WarehouseAjaxDatatableView(AjaxDatatableView):
    model = Warehouse
    title = 'I tuoi magazzini'
    initial_order = [["name", "asc"], ]
    length_menu = [[10, 20, 50, 100, -1], [10, 20, 50, 100, 'Tutti']]
    search_values_separator = '+'

    column_defs = [
        {'name': 'azioni', 'title': 'azioni', 'placeholder': True, 'searchable': False, 'orderable': False, },
        {'name': 'name', 'visible': True, },
        {'name': 'items', 'visible': True, },
        {'name': 'Valore totale', 'visible': True, },
        {'name': 'Valore d\'affitto', 'visible': True, },
    ]

    def customize_row(self, row, obj):
        pk = obj.pk
        row['azioni'] = f"""<a href="{reverse(f'detailWarehouseAdvanced', args={pk})}" class="action-item mr-2"><i
                                                     data-toggle="tooltip" title="" data-original-title="Visualizza dettagli" data-placement="right" class="fas fa-external-link-alt"></i></a>
                                                <a href="{reverse(f'updateWarehouse', args={pk})}" class="action-item mr-2"><i
                                                         data-toggle="tooltip" title="" data-original-title="Modifica" data-placement="right" class="fas fa-pencil-alt"></i></a>
                                                         <a href="{reverse(f'deleteWarehouse', args={pk})}" class="action-item text-danger mr-2"><i
                                                         data-toggle="tooltip" title="" data-original-title="Elimina" data-placement="right" class="fas fa-trash"></i></a>
                                                        """
        n_oggetti = obj.itemlist.all().count()
        row['items'] = f""" {n_oggetti} """
        row['Valore totale'] = f"""{str(obj.get_total_value).replace('.', ',')} €"""
        row['Valore d\'affitto'] = f"""{str(obj.get_total_rent).replace('.', ',')} €"""

DateFields are not searchable

Hello,
I noticed that a table containing a datefield in its columns won't enable the search function on that column.
if you type text into the column's searchbox, nothing will happen.

This behavior can be observer even in the example datatable provided by the readme:
http://django-ajax-datatable-demo.brainstorm.it/tracks/
The problem happens only when using the search box in the column, and not with the generic searchbox that search on all the fields, nor in the custom filter added there.

immagine

Discuss HTML injection in the documentation

The table doesn't prevent HTML injection in any way. So everything is left on the implementator.
It should be at least mentioned in the documentation with solution (I found it by using customize_row and from django.utils.html import escape).

Showing recordsTotal and recordsFiltered as same value

As i tried to filter records on table, it shows only filtered record count and not actual records count before filtering -
http://django-ajax-datatable-demo.brainstorm.it/tracks/

It should as excepted like actual jquery datatable plugin - https://datatables.net/
Showing 1 to N of N entries (filtered from 57 total entries)

"recordsTotal": paginator.count,

"recordsFiltered": paginator.count,

ZeroDivisionError: integer division or modulo by zero on filtered or empty table when selecting page

Buongiorno,

We're having some problems with the server side of this library. The problem occurs when selecting " show all entries" when the table is filtered or there are no records in the table; see below.
image

The minimum reproducible example app:
https://github.com/oshawa-connection/django-ajax-datatable-min-example

The error in full:

ZeroDivisionError at /ajax_datatable/permissions/

integer division or modulo by zero
Request Method: POST
http://127.0.0.1:8000/ajax_datatable/permissions/
3.2.5
ZeroDivisionError
integer division or modulo by zero
C:\Python39\lib\site-packages\ajax_datatable\views.py, line 689, in get_response_dict
C:\Python39\python.exe
3.9.5
['C:\Users\fleminjw\Documents\temp\django\mysite', 'C:\Python39\python39.zip', 'C:\Python39\DLLs', 'C:\Python39\lib', 'C:\Python39', 'C:\Users\fleminjw\AppData\Roaming\Python\Python39\site-packages', 'C:\Python39\lib\site-packages', 'C:\Python39\lib\site-packages\win32', 'C:\Python39\lib\site-packages\win32\lib', 'C:\Python39\lib\site-packages\Pythonwin']
Wed, 28 Jul 2021 07:50:28 +0000

You’re seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard page generated by the handler for this status code.

We are happy to provide a PR for this issue if necessary.
Django==3.2.5
django-ajax-datatable==4.2.1

Cordiali saluti

Pass *args **kwargs to get_initial_queryset()

Hi, I had to monkey patch get like this:

def get(self, request, *args, **kwargs):
    self.milestone = kwargs['milestone']
    return super(TaskListInProgAPI, self).get(request, *args, **kwargs)

so that I could read my url paramters. We could pass these directly to get_initial_queryset()? Is there another way to use these when overriding get_initial_queryset()?

m2m_foreign_field TypeError when foreign field is null in database

current_value = ', '.join(list_values)

Hi,

Congrats for this project, it is very useful and easy to get results even when we do not know how it works deeply.
I'm just starting using your module but I think I found a bug. So forgive me if I'm mistaking.

I want to display a ManyToMany field value which is not always available in the database (the field can be NULL).
When the DB field is NULL, the code crashes at line 227 with the following error :

File "/usr/local/lib/python3.9/site-packages/ajax_datatable/columns.py", line 227, in get_foreign_value
    current_value = ', '.join(list_values)
TypeError: sequence item 0: expected str instance, NoneType found

It would be interesting to check if list_values is None and put blank or a default value if it is None.

Thank you

support for django 3.2

hi
could you please add support for django 3.2 >
bcz im using django 3.2
but when installing this module its automatically downgrading to 3.1.6

Showing related objects as columns. Howto?

Hi,
I just found this package: Thanks already for providing this awesome piece of work!
I was wondering if I could use it for my 1-to-many situation though:

I have two Django models, Item and Prop.
Each Item can have up to 2 related Prop objects where Prop.ptype isalways in ['P1', 'P2'].
(In reality, there are many more Prop ptypes).

class Item(models.Model):
    name = models.TextField(blank=True, null=True)

class Prop(models.Model):
    ptype = models.TextField(blank=True, null=True)
    value = models.TextField(blank=True, null=True)
    item = models.ForeignKey(Item, on_delete=models.CASCADE)


# add some content
i1 = Item.objects.create(name='I1')
i2 = Item.objects.create(name='I2')
Prop.objects.create(ptype='P1', value='a', item=i1)
Prop.objects.create(ptype='P2', value='b', item=i1)
Prop.objects.create(ptype='P1', value='x', item=i2)

This situation in the database:

> select * from item;
 id | name |
----+------+-
  1 | I1   |
  2 | I2   |

> select * from prop;
 | ptype | value | item_id |
-+------+-------+---------+-
 | P1   | a     | 1       |
 | P2   | b     | 1       |
 | P1   | x     | 2       |

For all Item objects, I want to display a datatable of the following format:

 Name | P1 | P2 |
------+----+----+-
  I1  | a  | b  |
  I2  | x  | -  |

I can do this by using:

from . models import Item, Prop
class AjaxTest_Callback(AjaxDatatableView):
    model = Item
    initial_order = [['name', 'asc'], ]
    PROP_TYPES = ['P1', 'P2']

    # first column is item id
    column_defs = [
        {'name': 'name', 'visible': True, 'searchable': False},
    ]

    # add prop columns for all properties
    for p in PROP_TYPES:
        column_defs.append({'name': p, 'visible': True, 'searchable': False, 'orderable': True})

    # row by row, add foreign key values to the prop columns
    def customize_row(self, row, obj):
        for p in self.PROP_TYPES:
            entry = obj.prop_set.filter(ptype=p)
            row[p] = entry[0].value if entry else '-'

However, if i want to have the prop columns searchable, this does not work any more since P1/P2/P3 are not part of the Item model.
So I assume my approach is not good after all.
I was looking into defining foreign_field entries in column_defs, but I do not see how this could we used to solve my problem.

Could somebody pls give me a pointer to the right direction?

TIA

Filter a Placeholder column

Hello @morlandi,

Firstly bravo for this project, I am using it and it is so helpful.

I have an issue with filtering a Placeholder column.
This column is a concatenation of its value and 3 other columns.

My column is defined as such
{'name': 'column_1', 'placeholder': True, 'visible': True, 'searchable': True, 'orderable': False,},
And then
def customize_row(self, row, obj):
row['column_1'] = "

" + column_1+ column_2+ column_3+ column_4+ "
"

The filter only works for values issued from column_1, so I guess it is filtering before the row is assigned with my concatenation.

Is there a way I can filter a Placeholder column using its final value ?

Thanks a lot

ps : column_1 / 2/ / 3/ 4 being the different columns of my model

Column search does not work

Hello everyone. Added general search and automatically added column search. So, the general search works, but the column does not.

search1
search2

If you need more information, please tell me what

Null/empty searches?

Wanted to reach out to see if there were any options for null/empty searches? Doesn't seem possible with text searches, nor with the select searches.

Thank you in advance,

Juan

filtering multiple values - checkbox like interface

Hi,
Firstly - great project - extremely helpful !

Though, I wonder if there's a good way on top of the choices and text filters to have a predefined filter for multiple selections within a list of choices given to a user- i.e. as in excel "filter" where user can select multiple values.

f.e. where drop down filter would be:

  • A
  • B
  • C
  • D
  • E

Query itself would be myQuery(A | B | C)

You present a similar example function with text based input and "OR" operator, though I wonder if there's a good way to integrate such a drop down selection within the table styling, so it's more natural for the user, instead of having a list of these selections somewhere detached from the table.

I'm afraid this may be a missing feature within datatable, though looking at the examples & your codebase it appears that you have spent a good time with this extension - therefore there's a chance that you have already tackled this problem.

In the end, what I am looking foris a similar menu when you click funnel on this example:
https://js.devexpress.com/Demos/WidgetsGallery/Demo/DataGrid/Filtering/jQuery/Light/

Thanks for any suggestions

I want to add custom date range filter, but couldn't success

I want to make same as below example

i am using the following code

Screen Shot 2021-03-08 at 4 22 43 AM

ajax_datatable_views.py

`
class UserLogAjaxDatatableView(AjaxDatatableView):
model = Change
initial_order = [["date_created", "desc"], ]
Rec_Count = model.objects.all().count()
if Rec_Count > 500:
length_menu = [[10, 25, 50, 100], [10, 25, 50, 100]]
else:
length_menu = [[10, 25, 50, 100, -1], [10, 25, 50, 100, _("All")]]
search_values_separator = '+'
latest_by = "date_created"
show_date_filter = True

column_defs = [
    {'name': 'id', 'visible': False},
    {'name': 'date_created', 'searchable': True},
    {'name': 'user', 'foreign_field': 'user__username','visible': True, 'searchable': True},
    {'name': 'content_type', 'foreign_field': 'content_type__model','visible': True, 'searchable': True},
    {'name': 'object_repr', 'searchable': True},
    {'name': 'action', 'searchable': True},
    {'name': 'action1', 'data': None, 'visible': True, 'searchable': False, 'orderable': False, 'title':_('Action'), 'width': '50',},
]

def customize_row(self, row, obj):
    # 'row' is a dictionary representing the current row, and 'obj' is the current object.
    change_perm = '<button type="button" class="view-Log btn btn-outline-warning effect waves-light btn-xs" data-id="%s" title= "%s" ><i class="fe-eye"></i></button>'
    row['action1'] = ''

    if self.request.user.has_perm('crm.change_Log'):
        row['action1'] = \
            change_perm \
            % (reverse('crm:view_logging', args=(obj.pk,)),_("Edit"))

    return

`

list-log.html

`
$( document ).ready(function() {
function hideSearchInputs(columns) {
for (i=0; i<columns.length; i++) {
if (columns[i]) {
$('.filterhead:eq(' + i + ')' ).show();
} else {
$('.filterhead:eq(' + i + ')' ).hide();
}
}
}
AjaxDatatableViewUtils.initialize_table(
$('#table_id'),
"{% url 'crm:ajax_datatable_logging' %}",
{
// extra_options (example)
processing: false,
autoWidth: false,
full_row_select: false,
scrollX: true,
colReorder: true,
"pagingType": "full_numbers",
responsive: true,

                dom: '<"top"<"row"<"col-md-6"l><"col-md-6">>>Prt<"bottom"<"row"<"col-md-6"i><"col-md-6"pB>>><"clear">',
                    language: {
                        buttons: {
                            "collection": "{% trans "Columns" %}",
                            "copy": "{% trans "Copy" %}",
                            "csv": "{% trans "CSV" %}",
                            "print": "{% trans "Print" %}",
                            copyTitle: '{% trans "Copy to clipboard" %}',
                            copySuccess: {
                                _: '{% trans "Copied %d rows to clipboard" %}',
                                1: '{% trans "Copied one row to clipboard" %}'
                            }
                        },
                        "sEmptyTable":     "{% trans "No data available in table" %}",
                        "sInfo":           "{% trans "Showing _START_ to _END_ of _TOTAL_ entries" %}",
                        "sInfoEmpty":      "{% trans "Showing 0 to 0 of 0 entries" %}",
                        "sInfoFiltered":   "{% trans "(filtered from _MAX_ total entries)" %}",
                        "sInfoPostFix":    "",
                        "sInfoThousands":  ",",
                        "sLengthMenu":     "{% trans "Show _MENU_ entries" %}",
                        "sLoadingRecords": "{% trans "Loading..." %}",
                        "sProcessing":     "{% trans "Processing..." %}",
                        "sSearch":         "{% trans "Search:" %}",
                        "sZeroRecords":    "{% trans "No matching records found" %}",
                        "oPaginate": {
                            "sFirst":    "{% trans "First" %}",
                            "sLast":     "{% trans "Last" %}",
                            "sNext":     "{% trans "Next" %}",
                            "sPrevious": "{% trans "Previous" %}"
                        },
                        "oAria": {
                            "sSortAscending":  "{% trans ": activate to sort column ascending" %}",
                            "sSortDescending": "{% trans ": activate to sort column descending" %}"
                        }
                    },
                    columnDefs: [
                        { responsivePriority: 1, targets: 1,},
                        { responsivePriority: 2, targets: 6,},
                    ],
                    buttons: [
                            { extend: 'collection', className: 'btn-light', buttons: [ 'columnsToggle' ]},
                            {% if perms.crm.can_copy %}
                                { extend: 'copy', className: 'btn-light'},
                            {% endif %}
                            {% if perms.crm.can_csv %}
                                { extend: 'csv', className: 'btn-light' },
                            {% endif %}
                            {% if perms.crm.can_print %}
                                { extend: 'print', className: 'btn-light' },
                            {% endif %}
                    ],
                    drawCallback: function (settings) {
                        $(".view-Log").each(function () {
                          $(this).modalForm({formURL: $(this).data('id')});
                        });
                        $('table select').selectize({
                            sortField: 'text',
                            dropdownParent: "body",
                            allowEmptyOption: false,
                        });
                      $('.dt-buttons').detach().prependTo('#controlPanel')
                      $('table input').addClass("form-control");
                },
            }, {
                // extra_data
                // ...
            },
        );
    });

`

Disable row-details

Hi

Thanks for the great tool.

I was wondering if there is a way to disable the row-details. my datatable contains edit button on each row. I am having a problem with my edit button if clicked, the row-details shows and then I am taken to the edit page. Is there a way to disable the row-details so it doesn't show when the edit button is clicked?

Support for ManyToMany fields

By now, it's very limited; what I'm doing in the example project is:

  • render the M2M column "manually" in customize_row()
  • disable searching on it

Some specific code is needed in build_column_filter() to allow searching,
based on some variation of the following snippet:

tags = Tag.objects.filter(name__in=[search_value, ]), or Tag.objects.filter(name__icontains=search_value) ???
then:
queryset = queryset.filter(tags__in=tags)

For this to work, an indication of the field to be used in the related Model ("name" in the example above)
must the supplied (probably in 'foreign_field' attribute)

filter field

Hi,
is it possible to make the filter select field when the 'choices': True to be searchable as well this will be useful for the field has a lot of values

Thanks

If csrftoken cookie is set to HttpOnly, getCookie will not be able to fetch the token

Relates to issue #4 with more information.

image

If a Django project setting sets the CSRF_COOKIE_HTTPONLY = True then GetCookie function will not work. It becomes a problem for us if we want to keep our site secure, including cookies to prevent CSRF. Refer to Django documentation for an alternative: Getting CSRF token value when CSRF_COOKIE_HTTPONLY=True

For more information about HttpOnly: HTTP cookie - Secure and HttpOnly

Allow multiple sorting for each column

Use case: you have a list of addresses like:

street number
aaa 3
aaa 10
aaa 10/A
aaa 2/B

Suppose that an hidden "normalized_number" has been added to support "natural sorting":

street number normalized_number
aaa 3 00000003
aaa 10 00000010
aaa 10/A 00000010/A
aaa 2/B 00000002/B

In this case, you wish to show (street + number) but sort on (street, normalized_number).

This might be solved with the optional "sort_field" column attribute, i.e.:

'sort_field': 'street,normalized_number'

then refactoring sort_queryset() accordingly

Date-range filter

Hello,

I face with a strange behaviour with date range filter. (native one without change or my custom below) : The table return only on row :-(.

fields are set:

    show_date_filters = True
    latest_by = "ren_departure_date"

ren_departure_date is a DateField.

My custom range-filter (flatpickr)

 AjaxDatatableViewUtils.init({
    search_icon_html: '<i class="fa fa-search"></i>',
    language: {
    },
    fn_daterange_widget_initialize: function(table, data) {
        var wrapper = table.closest('.dataTables_wrapper');
        var toolbar = wrapper.find(".toolbar");
        toolbar.html(
            '<div class="daterange" style="float: left; margin-right: 6px;">' +
            'Du: <input type="date" id="date_from" name="date_from" class="date_from" autocomplete="off">' +
            '&nbsp;&nbsp;' +
            'Au: <input type="date" id="date_to" name="date_to" class="date_to" autocomplete="off">' +
            '</div>'
        );
        var date_pickers = toolbar.find('.date_from, .date_to');
        var dt_to ;
        var dt_from ;
        dict_date = {
            dateFormat: "Y-m-d",
            enableTime: false,
            locale: "fr",
            noCalendar: false,
            altFormat: "Y-m-d",
            //defaultDate: today
            onChange: function(selectedDates, dateStr, instance){
                var id = instance._input.getAttribute("id")
                if(id == 'date_from'){
                    dt_from = moment(dateStr).format("YYYY-MM-DD")
                }
                if(id == 'date_to'){
                    dt_to = moment(dateStr).format("YYYY-MM-DD")
                }
                console.log(dt_from, dt_to)
                if(dt_from != undefined && dt_to != undefined){
                    table.data('date_from', dt_from );
                    table.data('date_to', dt_to);
                    table.api().draw();
                }
            }
        }
        date_pickers.flatpickr(dict_date);
    }
});

Thanks for help.

Regards

Hidden columns are possible to filter

I wanted to add filter on hidden column by javascript, but even if I explicitly set the column as:

 {'name': 'is_private', 'visible': False, 'searchable': True},

it is not possible to filter single hidden column by Javascript calls like

javascript:$('#datatable_assets').DataTable().columns(16).search('window').draw();

I fixed this by overriding the searchable value:

    def filter_queryset(self, params, qs):
        # fix hidden column searchable
        params['column_links'][11].searchable = True
        return super().filter_queryset(params, qs)

nested choices/autofilter columns

Any suggestions how one would implemented nested choices/autofilter columns? I have a table with a number of columns, which can be filtered by choices, but if you select a filter for one column, then the choices for the other columns would need to be reduced based on the selection for the first column

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.