我在 Django 应用程序中使用 Plotly Py。我的网络应用程序中有两个主题:深色和浅色。 如果选择浅色主题,则图表背景为白色,如果选择深色主题,则图表背景设置为黑色。这是分别在 dark_theme_template 和 light_theme_template 中使用以下代码完成的。
我遇到的问题是,当一个用户更改主题时,当另一个用户刷新或点击回调时,它会影响另一个用户的图表。
import plotly.io as pio
from plotly.graph_objs import Layout
import plotly.graph_objects as go
dark_template_layout = Layout(
images=[
dict(
source="/static/img/images/watermark/Anahit-SVG-LOGO-GreyScale-4.svg",
name="Anahit",
xref="paper",
yref="paper",
x=0.5,
y=0.5,
sizex=0.5,
sizey=0.4,
xanchor="center",
yanchor="middle",
layer="below",
opacity=0.1,
)
],
annotationdefaults={
"arrowcolor": "#f2f5fa",
"arrowhead": 0,
"arrowwidth": 1,
},
autotypenumbers="strict",
coloraxis={"colorbar": {"outlinewidth": 0, "ticks": ""}},
colorway=[
"#636efa",
"#EF553B",
"#00cc96",
"#ab63fa",
"#FFA15A",
"#19d3f3",
"#FF6692",
"#B6E880",
"#FF97FF",
"#FECB52",
],
font={
"family": "Mulish, sans-serif",
"size": 16,
"color": "#a9afc3",
},
### title ###
title={
"font": {
"family": "Poppins, sans-serif",
"size": 15,
"color": "white",
},
### control position of title
# "y": 0.5,
"x": 0.5,
# "xanchor": "right",
# "yanchor": "middle",
},
hoverlabel={"align": "left"},
# Keep adding others as needed below
hovermode="closest",
mapbox={"style": "dark"},
**paper_bgcolor="#080a12",**
**plot_bgcolor="#080a12",**
shapedefaults={"line": {"color": "#a9afc3"}},
sliderdefaults={
"bgcolor": "#C8D4E3",
"bordercolor": "rgb(17,17,17)",
"borderwidth": 1,
"tickwidth": 0,
},
updatemenudefaults={"bgcolor": "#506784", "borderwidth": 0},
xaxis=dict(
automargin=True,
gridcolor="#283442",
linecolor="#506784",
title={"standoff": 15},
zerolinecolor="#283442",
zerolinewidth=2,
rangeselector={"activecolor": "#db5943", "bgcolor": "black"},
showgrid=False,
tickfont = dict(size=12),
titlefont = dict(size = 15),
),
yaxis=dict(
automargin=True,
gridcolor="#283442",
linecolor="#506784",
zerolinecolor="#283442",
zerolinewidth=2,
showgrid=True,
tickfont = dict(size=12),
titlefont = dict(size = 15),
# rangeselector = {"activecolor": "#db5943", "bgcolor": "#4d5160"},
),
modebar=dict(
activecolor="white",
),
legend=dict(
font=dict(
size=12,
),
),
)
# config for bar plots in dark theme
dark_template_bar_plot_config = [
go.Bar(marker=dict(color="#db5943")),
go.Bar(marker=dict(color="#e377c2")),
]
# config for scatter plots (e.g. line, scatter in dark theme)
dark_template_scatter_plot_config = [
go.Scatter(line=dict(color="#315bbc")),
go.Scatter(line=dict(color="#db5943")),
go.Scatter(line=dict(color="#41bc66")),
go.Scatter(line=dict(color="#bf8523")),
go.Scatter(line=dict(color="#e377c2")),
go.Scatter(line=dict(color="#17becf")),
go.Scatter(line=dict(color="#2ca02c")),
go.Scatter(line=dict(color="#ff7f0e")),
]
dark_template_heatmap_plot_config = [
go.Heatmap(textfont_size=17),
]
dark_template = go.layout.Template()
dark_template.layout = dark_template_layout
dark_template.data.bar = dark_template_bar_plot_config
dark_template.data.scatter = dark_template_scatter_plot_config
import plotly.io as pio
from plotly.graph_objs import Layout
import plotly.graph_objects as go
white_template_layout = Layout(
images=[
dict(
source="/static/img/images/watermark/Anahit-SVG-LOGO-GreyScale-1.svg",
name="Anahit",
xref="paper",
yref="paper",
x=0.5,
y=0.5,
sizex=0.5,
sizey=0.4,
xanchor="center",
yanchor="middle",
layer="below",
opacity=0.2,
)
],
annotationdefaults={
"arrowcolor": "#2a3f5f",
"arrowhead": 0,
"arrowwidth": 1,
},
autotypenumbers="strict",
coloraxis={"colorbar": {"outlinewidth": 0, "ticks": ""}},
colorway=[
"#636efa",
"#EF553B",
"#00cc96",
"#ab63fa",
"#FFA15A",
"#19d3f3",
"#FF6692",
"#B6E880",
"#FF97FF",
"#FECB52",
],
font={
"family": "Mulish, sans-serif",
"size": 16,
"color": "black",
},
### title ###
title={
"font": {
"family": "Poppins, sans-serif",
"size": 15,
"color": "black",
},
### control position of title
# "y": 0.5,
"x": 0.5,
# "xanchor": "right",
# "yanchor": "middle",
},
hoverlabel={"align": "left"},
# Keep adding others as needed below
hovermode="closest",
mapbox={"style": "dark"},
** paper_bgcolor="white",
plot_bgcolor="white",**
shapedefaults={"line": {"color": "#2a3f5f"}},
sliderdefaults={
"bgcolor": "#C8D4E3",
"bordercolor": "rgb(17,17,17)",
"borderwidth": 1,
"tickwidth": 0,
},
updatemenudefaults={"bgcolor": "#506784", "borderwidth": 0},
xaxis=dict(
automargin=True,
gridcolor="#d3d3d3",
linecolor="#d3d3d3",
title={"standoff": 15},
zerolinecolor="#d3d3d3",
zerolinewidth=2,
rangeselector={"activecolor": "#db5943", "bgcolor": "white"},
showgrid=False,
tickfont = dict(size=12),
titlefont = dict(size = 15),
),
yaxis=dict(
automargin=True,
gridcolor="#d3d3d3",
linecolor="#d3d3d3",
zerolinecolor="#d3d3d3",
zerolinewidth=2,
showgrid=True,
tickfont = dict(size=12),
titlefont = dict(size = 15),
),
modebar=dict(
activecolor="black",
),
legend=dict(
font=dict(
size=12,
),
),
)
# config for bar plots in dark theme
white_template_bar_plot_config = [
go.Bar(marker=dict(color="#db5943")),
go.Bar(marker=dict(color="#e377c2")),
]
# config for scatter plots (e.g. line, scatter in dark theme)
white_template_scatter_plot_config = [
go.Scatter(line=dict(color="#315bbc")),
go.Scatter(line=dict(color="#db5943")),
go.Scatter(line=dict(color="#41bc66")),
go.Scatter(line=dict(color="#bf8523")),
go.Scatter(line=dict(color="#e377c2")),
go.Scatter(line=dict(color="#17becf")),
go.Scatter(line=dict(color="#2ca02c")),
go.Scatter(line=dict(color="#ff7f0e")),
]
white_template = go.layout.Template()
white_template.layout = white_template_layout
white_template.data.bar = white_template_bar_plot_config
white_template.data.scatter = white_template_scatter_plot_config
设置模板并将深色主题设置为默认
import plotly.io as pio
from plotly.graph_objs import Layout
import plotly.graph_objects as go
from apps.dashboards.themes.dark_theme import dark_template
from apps.dashboards.themes.white_theme import white_template
pio.templates["white_template"] = white_template
pio.templates["dark_template"] = dark_template
pio.templates.default = "dark_template"
当用户更改主题时,将调用此视图
class ChangeTheme(View):
def post(self, request):
response = {}
try:
light_mode = True if request.POST.get("light_mode") == "true" else False
if light_mode:
request.session["light_mode"] = True
request.session.save()
pio.templates.default = "white_template"
else:
request.session["light_mode"] = False
request.session.save()
pio.templates.default = "dark_template"
except Exception as error:
return HttpResponse(json.dumps(response), content_type="application/json")
我知道 pio.template.default = '' 导致了问题,因为它是跨应用程序全局设置的。因此,当另一个用户更改主题时,系统上的所有其他用户都会更改主题。
为了确保每个用户的主题偏好独立于其他用户,为不同用户维护单独的主题而不受全局干扰,建议的最佳实践是什么?我如何重构我的代码来实现这一目标? 预先感谢您的协助!
我知道
导致了这个问题,因为它是跨应用程序全局设置的。pio.template.default = ''
正确:这意味着对其进行的任何更改都会影响所有用户,无论他们个人的主题偏好如何。
建议的最佳实践是不更改全局默认值,而是在渲染图表时根据用户的主题首选项动态设置每个图表的模板。
将每个用户的主题偏好存储在其会话中或数据库中的配置文件模型中。
为用户渲染图表时,获取他们的主题首选项并应用适当的主题。
GibbsConsulting/django-plotly-dash
第67期和GibbsConsulting/django-plotly-dash/demo/demo/views.py
中提到的
首先,更新
ChangeTheme
视图以仅存储用户的首选项而不修改全局设置:
class ChangeTheme(View):
def post(self, request):
response = {}
try:
light_mode = True if request.POST.get("light_mode") == "true" else False
request.session["light_mode"] = light_mode
request.session.save()
except Exception as error:
# handle error
return HttpResponse(json.dumps(response), content_type="application/json")
然后在渲染图表时动态应用主题。
例如,假设您有一个创建并返回图表的函数/视图
render_chart
。更新此函数以使用特定于用户的模板:
def render_chart(request):
# Retrieve user's theme preference
light_mode = request.session.get("light_mode", False)
# Create chart
fig = go.Figure()
# Based on the user preference, apply the correct theme
if light_mode:
fig.update_layout(template="white_template")
else:
fig.update_layout(template="dark_template")
# rest of the chart creation process
return fig
现在,即使多个用户同时更改主题,他们也不会干扰彼此的图表主题,因为主题是在图表渲染时应用的并且是特定于用户的。