【问题标题】:Wagtail add functions to models.pyWagtail 向 models.py 添加函数
【发布时间】:2022-12-05 23:01:19
【问题描述】:

我正在尝试在鹡鸰主页上制作自定义绘图。 我走到这一步了。我通过更改返回到模板的上下文来覆盖 wagtail 页面模型。我这样做是否正确,这在 models.py 中可能吗?

先进的thnx。

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)

    # https://stackoverflow.com/questions/32626815/wagtail-views-extra-context
    def get_context(self, request):
        context = super(CasPage, self).get_context(request)
        context['output'] = output
        return context

【问题讨论】:

    标签: django wagtail


    【解决方案1】:

    一种正确的轨道。不过,您应该将所有绘图代码移动到它自己的方法中。目前,它会在站点初始化时运行绘图代码,然后将其存储在内存中。

    然后可以通过三种常用方法将绘图绘制到呈现的页面。

    1. 正如您对上下文所做的那样
    2. 作为页面类的属性或方法
    3. 作为从模板中调用的模板标签

      前两个或多或少具有相同的效果,除了第二个使属性在任何地方都可用,而不仅仅是模板。上下文方法在页面开始呈现之前运行,其他两个发生在该过程中。我想唯一真正的区别是,如果您使用模板缓存,上下文将始终在每次加载页面时运行,其他两个仅在缓存无效或代码从缓存中转义时运行(用于片段缓存)。

      要将绘图作为页面类的属性调用,您只需将代码提取到带有 @property 装饰器的 def 中:

      class CasPage(Page):
          ....
          @property
          def plot(self):
              try:
                  conn = psycopg2.connect(
                      database="xxxx",
                      user="xxxx",
                      password="xxxx",
                      host="xxxxxxxxxxxxx",
                      port=xxxxx,
                  )
                  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")
                      )
                  return plotly.plot(fig1, output_type='div', include_plotlyjs=False)        
                  
              except Exception as e:
                  print(f"{type(e).__name__} at line {e.__traceback__.tb_lineno} of {__file__}: {e}")       
                  return None
      

      ^ 我还没有尝试过这段代码……它应该可以正常工作,但不能保证我没有打错字;)

      现在您可以在模板中使用{{ self.plot }} 访问您的绘图。

      如果你想坚持使用上下文,那么你会继续使用上面的 def,但只需将你的输出行修改为

      context['output'] = self.plot
      

      模板标签在 StructBlocks 中使用时更有用,而不是像这样的页面类的一部分。然后将所有绘图代码移动到模板标记文件中,注册它并在模板中使用 {% plot %} 调用它。 Wagtail 模板标签与 Django 一样工作:https://docs.djangoproject.com/en/4.1/howto/custom-template-tags/

      地块数据是否在站点数据库之外?如果没有,如果它被定义为模型,您可能可以通过 ORM 获取数据。如果是这样,可能值得在数据库服务器上编写一个视图(或者存储过程,如果你想传递参数)并调用它,而不是将 SQL 硬编码到你的 python 中。

      另一个考虑因素是页面加载时间——如果数据集很大,这可能需要一段时间并阻止页面加载。在这种情况下,您可能需要一个前端解决方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-25
      • 2023-03-23
      • 1970-01-01
      • 1970-01-01
      • 2020-10-21
      • 1970-01-01
      相关资源
      最近更新 更多