morlandi / django-ajax-datatable

A Django app which provides the integration of a Django project with the jQuery Javascript library DataTables.net
MIT License
204 stars 64 forks source link

Using ajax_datatable for admin template #98

Open michaeldacanay opened 1 year ago

michaeldacanay commented 1 year ago

The example_minimal code was very useful in understanding how ajax_datatable works. However, how would I use ajax_datatable to replace the default admin table (overriding the admin template)? It is a bit unclear to me. It seems that ajax_datatable requires a urls.py / views.py / ajax_datatable_views.py structure. However, most documentation overriding admin template seems to just override the html file.

thank you for your time!

morlandi commented 1 year ago

Hello @MichaelDacanay, thanks for the interesting question.

When using DataTables.net in Ajax mode, two views are needed: the first "traditional" for rendering the HTML table, and the second "solicited via ajax" to react to user prompts.

Wanting to use django-ajax-datatable in the context of a Django admin changelist, I think it is necessary to override "change_list.html" and there (1) insert an HTML table and (2) invoke AjaxDatatableViewUtils.initialize_table() to associate to that HTML table a suitable AjaxDatatableView-derived view.

This app was been developed mainly to have a listing tool in the frontend, so I never had the need to use it in Django admin, but I think it should work.

michaeldacanay commented 1 year ago

Hi @morlandi, thank you so much for your reply. So far, I have been able to figure out that change_list_results.html (from https://github.com/django/django/blob/stable/1.4.x/django/contrib/admin/templates/admin/change_list_results.html) is the template to override. I am able to follow the steps you mentioned and display the sample Permissions datatable. My current challenge is populating the ajax_datatable with the Django template variables from change_list_results.html e.g., {% for result in results %}. But in the example_minimal, the data for the table is in an ajax_datatable_views.py. Would you know if it is possible to bring the Django template variables to the ajax_datatable_views.py or another way to populate the AjaxDatatableView-derived view? I believe the Django template variables differ for each model, so I think it is necessary to use the Django template variables. The other thought I had is having multiple AjaxDatatableView-derived views in ajax_datatable_views.py, similar to multiple admin.ModelAdmin-derived views, however I'm struggling to think about how to implement it.

morlandi commented 1 year ago

I would rather override change_list.html

The template doesn't need to know where the AjaxDatatableView-derived view lives; just provide a url to the latter, and refer to the url in the template

michaeldacanay commented 1 year ago

Thank you @morlandi for pointing me in the right direction. I am now using change_list.html with full path myproject/templates/admin/myapp/change_list.html:

{% extends 'admin/change_list.html' %}
{% load static %}

{% block extrastyle %}
    <link href="{% static 'ajax_datatable/css/style.css' %}" rel="stylesheet" />
    <link href="//cdn.datatables.net/1.10.22/css/jquery.dataTables.min.css" />
    <style>
        body {
            background-color: #eee;
            padding: 40px;
        }
        table {
            border: 2px solid #ccc;
            border-collapse: collapse;
            width: 80%;
        }
        table th {
            border: 1px solid #ccc;
            background-color: #333;
            color: #fff;
        }
        table td {
            border: 1px solid #ccc;
        }
        .dataTables_filter input {
            background-color: #ffe;
            margin: 8px 0;
        }
        .datatable-column-filter-row input {
            background-color: #ffe;
            border: none;
            padding: 0;
            margin: 0;
        }
        .dataTables_paginate {
            margin: 8px 0;
        }
        .paginate_button {
            border: 1px solid #ccc;
            padding: 4px;
            cursor: pointer;
            background-color: #ddd;
        }
    </style>
{% endblock %}

{% block content %}
    {{ block.super }}

    <!-- block content -->
    <h3>Minimal example for django-ajax-datatable</h3>
    <table id="datatable_permissions">
    </table>

    <!-- block extrajs -->
    <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
    <script type="text/javascript" src="{% static 'ajax_datatable/js/utils.js' %}"></script>
    <script src="//cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>

    <script language="javascript">

        $(document).ready(function() {
            AjaxDatatableViewUtils.initialize_table(
                $('#datatable_permissions'),
                "{% url 'myapp:ajax_datatable_permissions' %}",
                {
                    // extra_options (example)
                    processing: false,
                    autoWidth: false,
                    full_row_select: true,
                    scrollX: false
                }, {
                    // extra_data
                    // ...
                },
            );
        });
    </script>
{% endblock %}

In my MyModelAdmin in myapp/admin.py, I have:

class MyModelAdmin(admin.ModelAdmin):
    change_list_template = 'admin/myapp/change_list.html'
    ...

This is my current code. I have the ajax_datatable_views.py and urls.py in myapp similar to the set up in example_minimal (https://github.com/morlandi/django-ajax-datatable/tree/master/example_minimal/example_minimal). I see that there are two tables: the table with data I want (from the {{ block.super }} and the table from ajax_datatable_views.py with the dummy data. The {{ block.super }} table seems to borrow the stylings from the extrastyle block, but does not have the search bar for each column. Is there a way to combine the two so that there is one table with the real data, and have the AJAX search?

michaeldacanay commented 1 year ago

I believe the table from {{ block.super }} comes from the content block in https://github.com/django/django/blob/stable/1.4.x/django/contrib/admin/templates/admin/change_list.html:

      {% block result_list %}
          {% if action_form and actions_on_top and cl.full_result_count %}{% admin_actions %}{% endif %}
          {% result_list cl %}
          {% if action_form and actions_on_bottom and cl.full_result_count %}{% admin_actions %}{% endif %}
      {% endblock %}
      {% block pagination %}{% pagination cl %}{% endblock %}