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

如何为客户端处理的DataTable实现懒加载?附性能优化需求

Hey there! Let's tackle this loading issue step by step. First, getting the first page to show up instantly while the rest loads in the background is totally doable, and we can also add several optimizations to speed things up overall. Let's break it down:


1. Implement Instant First Page + Background Preloading

The core idea is to use DRF's pagination to return the first page immediately, then asynchronously fetch remaining pages in the background and cache them on the frontend. Here's how to adjust your code:

First, Fix Serializer Typo

I notice a mismatch in your BibSerializer—your Bibrest51 model uses tema and tipo as foreign key fields, but the serializer defines temas and tipos. That'll break the nested serialization. Let's fix that first:

# serializers.py
class BibSerializer(serializers.ModelSerializer):
    tema = TemaSerializer(read_only=True)  # Corrected from "temas"
    tipo = TipoSerializer(read_only=True)  # Corrected from "tipos"
    class Meta:
        model = Bibrest51
        fields = ('autor', 'ano', 'titulo', 'referencia', 'tipo', 'tema')

Add Pagination to DRF View

Create a pagination class and update your view to use it (I'll assume you're using a ViewSet; adjust if you're using a function-based view):

# views.py
from rest_framework.pagination import PageNumberPagination
from rest_framework.viewsets import ReadOnlyModelViewSet
from .models import Bibrest51
from .serializers import BibSerializer

class StandardResultsSetPagination(PageNumberPagination):
    page_size = 10  # Match your desired first page size
    page_size_query_param = 'page_size'
    max_page_size = 1000

class BibrestViewSet(ReadOnlyModelViewSet):
    # Use select_related to avoid N+1 queries (more on this later!)
    queryset = Bibrest51.objects.select_related('tema', 'tipo').all()
    serializer_class = BibSerializer
    pagination_class = StandardResultsSetPagination

Frontend: Render First Page + Background Preload

Update your DataTable initialization to fetch the first page instantly, then preload remaining pages in the background:

$(document).ready(function() {
    let dataCache = {};
    let totalPages;
    const table = $('#your-table-id').DataTable({
        columns: [
            {data: 'autor'},
            {data: 'ano'},
            {data: 'titulo'},
            {data: 'referencia'},
            {data: 'tipo.tipo_nome'},
            {data: 'tema.tema_nome'}
        ],
        pageLength: 10,
        deferRender: true,  // Delay rendering off-screen rows for speed
        serverSide: false   // Handle pagination client-side with cache
    });

    // Fetch first page and render immediately
    $.ajax({
        url: '/api/bibrest/',
        method: 'GET',
        data: {page: 1},
        success: function(response) {
            totalPages = response.total_pages;
            dataCache[1] = response.results;
            table.clear().rows.add(response.results).draw();

            // Preload remaining pages in background with small delays
            for (let page = 2; page <= totalPages; page++) {
                setTimeout(() => {
                    $.ajax({
                        url: '/api/bibrest/',
                        method: 'GET',
                        data: {page: page},
                        success: function(pageResponse) {
                            dataCache[page] = pageResponse.results;
                        }
                    });
                }, (page - 1) * 300); // Avoid overwhelming server
            }
        }
    });

    // Override pagination to use cached data first
    table.on('page.dt', function() {
        const currentPage = table.page.info().page + 1; // DataTable uses 0-indexed pages
        if (dataCache[currentPage]) {
            table.clear().rows.add(dataCache[currentPage]).draw();
        } else {
            // Fallback if cache isn't ready yet
            $.ajax({
                url: '/api/bibrest/',
                method: 'GET',
                data: {page: currentPage},
                success: function(response) {
                    dataCache[currentPage] = response.results;
                    table.clear().rows.add(response.results).draw();
                }
            });
        }
    });
});

2. Additional Loading Speed Optimizations

Beyond the initial page load, these changes will drastically cut down overall loading time:

Database & Query Optimizations

  • Eliminate N+1 Queries: We already added select_related('tema', 'tipo') to the queryset—this fetches foreign key data in a single SQL query instead of one per row.
  • Add Indexes: If your database supports it, add indexes to frequently filtered/searched fields (e.g., autor, titulo) and confirm foreign key fields have indexes (Django usually adds these automatically, but double-check for your unmanaged tables).
  • Limit Serialized Data: Don't use __all__ in your nested serializers—only include fields you actually need:
    class TemaSerializer(serializers.ModelSerializer):
        class Meta:
            model = BibTema
            fields = ['tema_nome']  # Only return the field you use in the table
    
    class TipoSerializer(serializers.ModelSerializer):
        class Meta:
            model = Tipo
            fields = ['tipo_nome']
    

DRF Performance Tweaks

  • Cache Query Results: If your data doesn't update frequently, use Django's caching framework to cache pagination responses. For example, add a cache decorator to your view or use django-rest-framework-cache.
  • Disable Browsable API in Production: In your settings.py, remove the browsable API renderer to reduce overhead:
    REST_FRAMEWORK = {
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer',
        ]
    }
    

Frontend Optimizations

  • Compress Assets: Minify your JS/CSS files and use gzip compression on your server.
  • Lazy Load Off-Screen Data: If 3500 rows is too much to cache upfront, adjust the preload logic to only fetch pages as the user approaches them (e.g., preload page N+1 when the user is on page N).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:41:08