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

在Wagtail首页自定义Plotly图表:models.py中实现方式是否正确?

问题:Wagtail首页自定义Plotly图表的实现方式是否正确?能否在models.py中完成?

我正尝试在Wagtail首页制作自定义Plotly图表,目前已通过重写Page模型修改返回给模板的上下文。请问这种实现方式是否正确?能否在models.py中完成此操作?

以下是我的代码:

from django.db import models

from wagtail.models import Page
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

import psycopg2
from psycopg2 import sql
import pandas as pd
import plotly.graph_objs as go
from plotly.offline import plot

class CasPage(Page):
    body = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('body'),
    ]

    def get_connection(self):
        try:
            return psycopg2.connect(
                database="xxxx",
                user="xxxx",
                password="xxxx",
                host="xxxxxxxxxxxxx",
                port=xxxxx,
            )
        except:
            return False
    conn = get_connection()
    cursor = conn.cursor()

    strquery = (f'''SELECT t.datum, t.grwaarde - LAG(t.grwaarde,1) OVER (ORDER BY datum) AS 
      gebruiktgas
                FROM XXX
                     ''')

    data = pd.read_sql(strquery, conn)

    fig1 = go.Figure(
    data = data,
    layout=go.Layout(
        title="Gas-verbruik",
        yaxis_title="aantal M3")
        )

    output = plotly.plot(fig1, output_type='div', include_plotlyjs=False)

    def get_context(self, request):
        context = super(CasPage, self).get_context(request)
        context['output'] = output
        return context

解答

你的实现方式存在明显问题,不应该在models.py中这么写,具体问题和优化方案如下:

核心问题

  1. 类级别代码执行时机错误:你把数据库连接、数据查询、图表生成的代码直接写在类的顶层,这些代码会在Django服务启动时就执行一次,而不是在用户访问页面时动态执行。这会导致:

    • 数据库连接长期占用,无法随请求释放,容易引发连接池耗尽问题
    • 图表数据永远是服务启动时的旧数据,不会实时更新
    • 若启动时数据库不可用,整个Wagtail服务会直接报错
  2. 代码调用错误:你导入的是from plotly.offline import plot,但后面用了plotly.plot,会抛出NameError异常。

  3. 异常处理缺失:get_connection返回False后,后续直接调用conn.cursor()会崩溃,没有处理连接失败的逻辑。

正确的实现方式

可以在models.py的get_context方法内完成,但必须把所有动态逻辑放在方法内部(仅在请求时执行),优化后的代码如下:

from django.db import models

from wagtail.models import Page
from wagtail.fields import RichTextField
from wagtail.admin.panels import FieldPanel

import psycopg2
import pandas as pd
import plotly.graph_objs as go
from plotly.offline import plot

class CasPage(Page):
    body = RichTextField(blank=True)

    content_panels = Page.content_panels + [
        FieldPanel('body'),
    ]

    def get_context(self, request):
        context = super().get_context(request)
        
        # 所有动态逻辑放在get_context内,每次请求时执行
        try:
            # 建立数据库连接
            conn = psycopg2.connect(
                database="xxxx",
                user="xxxx",
                password="xxxx",
                host="xxxxxxxxxxxxx",
                port=xxxxx,
            )
            
            # 执行SQL查询
            strquery = '''SELECT t.datum, t.grwaarde - LAG(t.grwaarde,1) OVER (ORDER BY datum) AS 
                          gebruiktgas FROM XXX'''
            data = pd.read_sql(strquery, conn)
            
            # 关闭连接,避免资源泄漏
            conn.close()
            
            # 生成Plotly图表(需指定数据格式,原代码直接传data会报错)
            fig1 = go.Figure(
                data=[go.Scatter(x=data['datum'], y=data['gebruiktgas'])],
                layout=go.Layout(
                    title="Gas-verbruik",
                    yaxis_title="aantal M3"
                )
            )
            
            # 生成可嵌入的HTML代码
            output = plot(fig1, output_type='div', include_plotlyjs=False)
            context['output'] = output
            
        except Exception as e:
            # 捕获异常,避免页面崩溃,返回错误提示
            context['output'] = f"<p>图表加载失败:{str(e)}</p>"
        
        return context

额外建议

  1. 使用Django内置数据库连接:如果你的Wagtail项目已经配置PostgreSQL作为数据库,建议用django.db.connection执行查询,无需手动管理psycopg2连接,更安全可靠。
  2. 缓存图表结果:若数据不是实时更新的,可通过Django缓存框架缓存生成的output内容,减少数据库查询和图表生成的性能开销。
  3. 前端引入Plotly.js:因为设置了include_plotlyjs=False,需要在模板中手动引入Plotly.js的CDN或本地文件,否则图表无法渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 22:05:17