You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django用户求助:jQuery加载API数据后DataTable无法正常渲染

How to Properly Render DataTables with jQuery AJAX in Django

Hey there! Let's break down why your DataTables isn't working when loading data via jQuery AJAX, and fix it step by step.

The Core Issue

When you render data directly with Django templates, DataTables initializes on a fully populated table. But with AJAX, you're dynamically adding content after DataTables might have already initialized—so it doesn't recognize the new rows, and its features (sorting, pagination, styling) break.

Instead of manually building HTML strings, use DataTables' built-in methods to add rows. This ensures DataTables tracks all changes and maintains full functionality.

First, initialize an empty DataTable when the page loads:

$(document).ready(function() {
  // Initialize empty DataTable with your preferred options
  var table = $('#approvedData').DataTable({
    // Add options like pagination, sorting here if needed
    paging: true,
    searching: true
  });
});

Then update your fetchData function to use DataTables' API:

function fetchData() {
  $.ajax({
    type: 'GET',
    url: endpoint,
    success: function (data) {
      console.log(data);
      var table = $('#approvedData').DataTable();
      
      // Clear existing rows first to avoid duplicates
      table.clear();

      data.forEach(object => {
        let storyStatus = 'Story not finish';
        let colorClassName = "badge-danger";
        
        if (object.story_status === "sf") {
          colorClassName = "badge-success";
          storyStatus = "Story finish"
        }
        if (object.story_status === "fr") {
          colorClassName = "badge-success";
          storyStatus = "Approved"
        }

        // Add row directly via DataTables API
        table.row.add([
          object.id,
          `<a href="#">${object.title}</a>`,
          object.author,
          moment(object.created_on).fromNow(),
          `<span class="badge ${colorClassName}" id="story-status">${storyStatus}</span>`,
          `<div class="table-btns">
            <a href="${updateURL}update/${object.id}" class="table-btn table-btn--edit">
              <i class="icon ion-ios-create"></i>
            </a>
            <a href="#" class="table-btn table-btn--delete" data-pk="${object.id}">
              <i class="icon ion-ios-trash"></i>
            </a>
          </div>`
        ]);
      });

      // Draw the updated table
      table.draw();

      // Use event delegation for delete buttons (dynamic elements)
      $('#approvedData').off('click', '.table-btn--delete').on('click', '.table-btn--delete', function () {
        var pk = $(this).data('pk');
        var $row = $(this).closest('tr');
        
        swal({
          title: "Are you sure?",
          text: "You will not be able to recover this story!",
          icon: "warning",
          buttons: true,
          dangerMode: true,
        })
        .then((willDelete) => {
          if (willDelete) {
            $.ajax({
              url: '{% url "del" %}',
              type: 'POST',
              headers: { "X-CSRFToken": '{{csrf_token}}' },
              data: { pk: pk },
              success: function () {
                swal("Story has been deleted!", { icon: "success" });
                // Remove the row from DataTables and redraw
                table.row($row).remove().draw();
              }
            });
          } else {
            swal("Story is safe");
          }
        });
      });
    }
  });
};

// Initial data load
fetchData();
// Note: 2 seconds is way too frequent for refreshes—use 30+ seconds to avoid server strain
setInterval(fetchData, 30000);

Fix 2: If You Prefer Manual HTML Rendering

If you want to keep building HTML strings, you need to destroy and reinitialize DataTables after updating the table content:

function fetchData() {
  $.ajax({
    type: 'GET',
    url: endpoint,
    success: function (data) {
      console.log(data);
      var html = '';
      
      data.forEach(object => {
        let storyStatus = 'Story not finish';
        let colorClassName = "badge-danger";
        
        if (object.story_status === "sf") {
          colorClassName = "badge-success";
          storyStatus = "Story finish"
        }
        if (object.story_status === "fr") {
          colorClassName = "badge-success";
          storyStatus = "Approved"
        }

        html += `<tr>
          <td>${object.id}</td>
          <td><a href="#">${object.title}</a></td>
          <td>${object.author}</td>
          <td>${moment(object.created_on).fromNow()}</td>
          <td><span class="badge ${colorClassName}" id="story-status">${storyStatus}</span></td>
          <td>
            <div class="table-btns">
              <a href="${updateURL}update/${object.id}" class="table-btn table-btn--edit">
                <i class="icon ion-ios-create"></i>
              </a>
              <a href="#" class="table-btn table-btn--delete" data-pk="${object.id}">
                <i class="icon ion-ios-trash"></i>
              </a>
            </div>
          </td>
        </tr>`;
      });

      // Destroy existing DataTable instance
      $('#approvedData').DataTable().destroy();
      // Update table content
      $("#approvedList").html(html);
      // Reinitialize DataTable
      $('#approvedData').DataTable();

      // Event delegation for delete buttons
      $('#approvedData').off('click', '.table-btn--delete').on('click', '.table-btn--delete', function () {
        var pk = $(this).data('pk');
        var $row = $(this).closest('tr');
        
        swal({
          title: "Are you sure?",
          text: "You will not be able to recover this story!",
          icon: "warning",
          buttons: true,
          dangerMode: true,
        })
        .then((willDelete) => {
          if (willDelete) {
            $.ajax({
              url: '{% url "del" %}',
              type: 'POST',
              headers: { "X-CSRFToken": '{{csrf_token}}' },
              data: { pk: pk },
              success: function () {
                swal("Story has been deleted!", { icon: "success" });
                $('#approvedData').DataTable().row($row).remove().draw();
              }
            });
          } else {
            swal("Story is safe");
          }
        });
      });
    }
  });
};

Key Notes

  • Event Delegation: Always use on() with a parent element for dynamically added buttons (like delete) — direct click() bindings won't work on new rows.
  • Avoid Frequent Refreshes: A 2-second interval will hammer your server. Use a longer window (30+ seconds) or implement a smarter refresh trigger.
  • Check Resources: Ensure you've correctly included DataTables CSS and JS files in your template—missing resources are a common cause of style failures.

内容的提问来源于stack exchange,提问作者afi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 07:47:37