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

Django仪表盘按类别、月份、年份过滤实现咨询

Django仪表盘数据过滤:后端vs前端实现方案

一、后端过滤(推荐大流量/敏感数据场景)

核心逻辑

前端提交过滤参数(类别、年份、月份),后端通过Django ORM或DataFrame预处理数据,只返回符合条件的结果给前端渲染图表。

优势

  • 减少前端数据传输量,优化加载速度
  • 敏感数据不会暴露到前端,安全性更高
  • 利用数据库查询优化(如索引)提升过滤效率

代码实现

views.py(处理参数+过滤数据)

from django.shortcuts import render
import pandas as pd
from .models import YourDataModel  # 替换为你的数据模型

def home(request):
    # 获取前端传递的过滤参数
    category = request.GET.get('category', '')
    year = request.GET.get('year', '')
    month = request.GET.get('month', '')

    # 从数据库拉取数据并应用过滤
    queryset = YourDataModel.objects.all()
    if category:
        queryset = queryset.filter(category=category)
    if year:
        queryset = queryset.filter(date__year=year)
    if month:
        queryset = queryset.filter(date__month=month)

    # 转换为DataFrame并转JSON
    df = pd.DataFrame(list(queryset.values()))
    data_json = df.to_json(orient='records')

    # 准备过滤选项(给前端下拉框)
    categories = YourDataModel.objects.values_list('category', flat=True).distinct()
    years = YourDataModel.objects.values_list('date__year', flat=True).distinct().order_by('-date__year')
    months = YourDataModel.objects.values_list('date__month', flat=True).distinct().order_by('date__month')

    return render(request, 'home.html', {
        'data': data_json,
        'categories': categories,
        'years': years,
        'months': months
    })

home.html(添加过滤表单)

<div class="filter-bar">
    <select id="category-filter">
        <option value="">所有类别</option>
        {% for cat in categories %}
            <option value="{{ cat }}">{{ cat }}</option>
        {% endfor %}
    </select>
    <select id="year-filter">
        <option value="">所有年份</option>
        {% for year in years %}
            <option value="{{ year }}">{{ year }}</option>
        {% endfor %}
    </select>
    <select id="month-filter">
        <option value="">所有月份</option>
        {% for month in months %}
            <option value="{{ month }}">{{ month }}</option>
        {% endfor %}
    </select>
    <button id="apply-filter">应用过滤</button>
</div>

<div id="chart-container"></div>

<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="{% static 'js/home.js' %}"></script>
<!-- 隐藏的全量数据容器 -->
<script id="chart-data" type="application/json">{{ data|safe }}</script>

home.js(AJAX请求+更新图表)

document.addEventListener('DOMContentLoaded', () => {
    // 初始化图表
    const initialData = JSON.parse(document.getElementById('chart-data').textContent);
    let chart = initChart(initialData);

    // 绑定过滤按钮事件
    document.getElementById('apply-filter').addEventListener('click', () => {
        const params = new URLSearchParams({
            category: document.getElementById('category-filter').value,
            year: document.getElementById('year-filter').value,
            month: document.getElementById('month-filter').value
        });

        // 发起GET请求获取过滤后的数据
        fetch(`/?${params}`)
            .then(res => res.json())
            .then(filteredData => {
                updateChart(chart, filteredData);
            });
    });
});

// 初始化图表
function initChart(data) {
    const ctx = document.getElementById('chart-container').getContext('2d');
    return new Chart(ctx, {
        type: 'bar',
        data: {
            labels: data.map(item => item.date),
            datasets: [{
                label: '数据统计',
                data: data.map(item => item.value),
                backgroundColor: 'rgba(75, 192, 192, 0.6)'
            }]
        }
    });
}

// 更新图表数据
function updateChart(chart, newData) {
    chart.data.labels = newData.map(item => item.date);
    chart.data.datasets[0].data = newData.map(item => item.value);
    chart.update();
}

二、前端过滤(适合小数据量/实时交互场景)

核心逻辑

后端一次性返回全量数据,前端通过JS直接过滤数据后更新图表,无需请求后端。

优势

  • 无后端请求延迟,交互更流畅
  • 减少服务器请求压力

代码实现

views.py(仅返回全量数据)

from django.shortcuts import render
import pandas as pd
from .models import YourDataModel

def home(request):
    queryset = YourDataModel.objects.all()
    df = pd.DataFrame(list(queryset.values()))
    data_json = df.to_json(orient='records')

    categories = YourDataModel.objects.values_list('category', flat=True).distinct()
    years = YourDataModel.objects.values_list('date__year', flat=True).distinct().order_by('-date__year')
    months = YourDataModel.objects.values_list('date__month', flat=True).distinct().order_by('date__month')

    return render(request, 'home.html', {
        'data': data_json,
        'categories': categories,
        'years': years,
        'months': months
    })

home.js(前端过滤逻辑)

document.addEventListener('DOMContentLoaded', () => {
    const fullData = JSON.parse(document.getElementById('chart-data').textContent);
    let chart = initChart(fullData);

    document.getElementById('apply-filter').addEventListener('click', () => {
        const category = document.getElementById('category-filter').value;
        const year = document.getElementById('year-filter').value;
        const month = document.getElementById('month-filter').value;

        // 前端过滤数据
        let filteredData = fullData.filter(item => {
            const matchesCategory = !category || item.category === category;
            const matchesYear = !year || new Date(item.date).getFullYear().toString() === year;
            const matchesMonth = !month || (new Date(item.date).getMonth() + 1).toString() === month;
            return matchesCategory && matchesYear && matchesMonth;
        });

        updateChart(chart, filteredData);
    });
});

// initChart和updateChart函数同后端过滤方案
function initChart(data) {
    const ctx = document.getElementById('chart-container').getContext('2d');
    return new Chart(ctx, {
        type: 'bar',
        data: {
            labels: data.map(item => item.date),
            datasets: [{
                label: '数据统计',
                data: data.map(item => item.value),
                backgroundColor: 'rgba(75, 192, 192, 0.6)'
            }]
        }
    });
}

function updateChart(chart, newData) {
    chart.data.labels = newData.map(item => item.date);
    chart.data.datasets[0].data = newData.map(item => item.value);
    chart.update();
}

方案选择建议

  • 选后端过滤:数据量大于1万条、包含敏感数据、需要利用数据库索引优化查询时
  • 选前端过滤:数据量小于5000条、追求实时无刷新交互体验时

内容的提问来源于stack exchange,提问作者Gustavo Santos de Paula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:14:58