如何在Django Admin中实现数据聚合和透视表

2023-04-11 00:00:00 数据 聚合 透视

在 Django Admin 中实现数据聚合和透视表可以用 Django 的聚合函数和注解来实现。

聚合函数包括 SUM、AVG、COUNT、MAX、MIN 等,可以在 queryset 中使用 annotate() 方法进行注解。

例如,假设我们有一个模型类 Article,其中有一个字段 price 表示文章的价格。我们可以使用 annotate() 方法计算所有文章的平均价格:

from django.db.models import Avg
from myapp.models import Article

avg_price = Article.objects.aggregate(Avg('price'))

上述代码中,aggregate() 方法返回一个字典,其中键为聚合函数名称,值为计算结果。在本例中,聚合函数为 Avg,计算结果为所有文章价格的平均值。

注解还可以用于分组聚合。例如,我们可以使用 annotate() 和 values() 方法计算每个作者的平均文章价格:

from django.db.models import Avg
from myapp.models import Article

result = Article.objects.values('author').annotate(avg_price=Avg('price'))

在上述代码中,values() 方法指定要分组的字段,annotate() 方法指定要进行的聚合操作。执行此代码后,将为每个作者计算平均文章价格,并返回一个 QuerySet 对象,其中每个元素都是一个字典,包含作者字段和平均价格字段。

在 Django Admin 中,我们可以使用 list_display 属性将聚合结果显示在列表页面上。例如,假设我们有一个 Author 模型类,我们可以在 AuthorAdmin 中使用 annotate() 和 list_display 展示每个作者的平均价格:

from django.contrib import admin
from django.db.models import Avg
from myapp.models import Article, Author

class AuthorAdmin(admin.ModelAdmin):
    list_display = ('name', 'avg_price')

    def avg_price(self, obj):
        queryset = Article.objects.filter(author=obj)
        result = queryset.aggregate(Avg('price'))
        return result['price__avg']

admin.site.register(Author, AuthorAdmin)

在上述代码中,我们将 avg_price 方法添加为 AuthorAdmin 的一个实例方法,并将其添加到 list_display 中。在 avg_price 方法中,我们使用 filter() 方法过滤此作者的所有文章,然后使用 aggregate() 方法计算价格平均值,并返回结果。在列表页面中,将显示每个作者的名称和平均价格。

对于透视表,我们可以使用 pandas 库来实现。首先,我们需要在 Django 安装 pandas。然后,我们可以使用 queryset.values() 方法将数据序列化为字典,并使用 pandas 的 DataFrame 类来创建透视表。

例如,假设我们有一个模型类 Article,其中有 title、author、publish_date 和 price 四个字段。我们可以使用以下代码将所有文章按照作者和年份进行分组,并计算每组文章的平均价格:

from django.db.models import Avg
from myapp.models import Article
import pandas as pd

result = Article.objects.values('author__name', 'publish_date__year').annotate(avg_price=Avg('price'))
df = pd.DataFrame.from_records(result, index=['author__name', 'publish_date__year'])
pivot_table = df.pivot_table(values='avg_price', index='author__name', columns='publish_date__year')

在上述代码中,我们首先使用 values() 方法和 annotate() 方法计算平均价格。然后,我们使用 DataFrame.from_records() 方法将结果转换为 pandas 数据框。最后,使用 pivot_table() 方法创建透视表。

在 Django Admin 中,我们可以通过编写自定义视图来将透视表嵌入到一个页面中。

from django.http import HttpResponse
import pandas as pd
from myapp.models import Article

def pivot_table_view(request):
    queryset = Article.objects.values('author__name', 'publish_date__year').annotate(avg_price=Avg('price'))
    df = pd.DataFrame.from_records(queryset, index=['author__name', 'publish_date__year'])
    pivot_table = df.pivot_table(values='avg_price', index='author__name', columns='publish_date__year')
    html = pivot_table.to_html()
    return HttpResponse(html)

在上述代码中,我们编写了一个名为 pivot_table_view 的视图函数。该函数计算透视表,并使用 DataFrame.to_html() 方法将其转换为 HTML 字符串,最后用 HttpResponse 返回该字符串。我们可以在 Django Admin 的模板中通过添加一个 iframe 元素来嵌入透视表:

{% extends "admin/base_site.html" %}

{% block content %}
    <h1>Dashboard</h1>
    <iframe src="{% url 'pivot_table_view' %}" style="height:500px;width:100%;"></iframe>
{% endblock %}

在上述代码中,我们在 Dashboard 页面中添加了一个名为 pivot_table_view 的 iframe,其 URL 为 pivot_table_view 视图函数的 URL。该 iframe 将显示计算得到的透视表。

相关文章