今天我們來說明如何將gt
表格呈現於Django app中,內容參考自官方Solar Zenith Angles範例。
建立一個名為core
的django project。
django-admin startproject core .
建立一個名為gt
的django app(以下簡稱為gt app
)。
python manage.py startapp gt
將gt app
加入位於core/settings.py
內的INSTALLED_APPS
中。
# core/settings.py
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"gt",
]
於gt app
中建立urls.py
,並設定urlpatterns
。
# gt/urls.py
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
]
修改core/urls.py
,加入gt app
的urlpatterns
。
# core/urls.py
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path("admin/", admin.site.urls),
path("", include("gt.urls")),
]
index()
函數 # gt/views.py
from functools import cache
import polars as pl
from django.shortcuts import render
from great_tables import GT, html
from great_tables.data import sza
@cache
def get_sza():
return pl.from_pandas(sza)
def index(request):
sza_pivot = (
get_sza()
.filter((pl.col("latitude") == "20") & (pl.col("tst") <= "1200"))
.select(pl.col("*").exclude("latitude"))
.drop_nulls()
.pivot(values="sza", index="month", on="tst", sort_columns=True)
)
sza_gt = (
GT(sza_pivot, rowname_col="month")
.data_color(
domain=[90, 0],
palette=["rebeccapurple", "white", "orange"],
na_color="white",
)
.tab_header(
title="Solar Zenith Angles from 05:30 to 12:00",
subtitle=html("Average monthly values at latitude of 20°N."),
)
.sub_missing(missing_text="")
)
context = {"sza_gt": sza_gt.as_raw_html()}
return render(request, "gt/index.html", context)
分段說明如下:
get_sza()
會返回一個Polars DataFrame,是由gt
提供的sza
Pandas DataFrame轉換而來。由於DataFrame於此app中不會變動,所以可以將@cache(註1)裝飾在get_sza()
上。index()
為使用者以HTTP GET
訪問「"/"」時使用的函數。sza_pivot
為Polars DataFrame的整理過程;sza_gt
則為表格的製作過程。context = {"sza_gt": sza_gt.as_raw_html()}
為整合的關鍵。我們使用GT.as_raw_html()來生成HTML,並置於context
中。index.html
。其中,context
可以視為製作index.html
所需要的額外資訊。於gt app
中建立一個templates
資料夾,並於templates
資料夾中再建立一個gt
資料夾。最後於此資料夾中(即gt/templates/gt
)建立index.html
。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Django-GT Website</title>
</head>
<body>
<main>
<h1 style="text-align:center">Great Tables shown in Django</h1>
</main>
<div>
{{ sza_gt | safe}}
</div>
</body>
</html>
於index.html
中,我們可以使用Django template語法{{ sza_gt }}
來取得於context
所傳入的值。但請注意這邊必須使用| safe
這個filter來確認此HTML是安全的,如此才可於瀏覽器中順利呈現gt
表格。
由於gt app
並沒有使用到資料庫,所以此命令為選擇性執行。如果沒有執行,gt
表格也可正確呈現,只是命令列會有尚未migration的警告訊息。
python manage.py migrate
於命令列中執行下列指令:
python manage.py runserver
接著打開瀏覽器前往預設網址,如http://127.0.0.1:8000/,就可以見到下面這個漂亮的表格:
如果不喜歡於template中加入| safe
的話,可以改為在view function中添加。舉例來說,可以寫一個mark_gt_safe()
來幫忙在index()
中呼叫GT.as_raw_html()
:
# gt/views.py
...
from django.utils.safestring import mark_safe
def mark_gt_safe(gt):
if isinstance(gt, GT):
return mark_safe(gt.as_raw_html())
return gt
def index(request):
...
context = {"sza_gt": mark_gt_safe(sza_gt)}
return render(request, "gt/index.html", context)
這麼一來在index.html
中,就可以直接使用{{ sza_gt }}
來取得gt
表格的HTML格式,而不必使用{{ sza_gt | safe}}
了。
如果對裝飾器這個概念仍然不是那麼清楚的朋友,可以參考我於2023年鐵人賽的系列文 ── Python十翼:與未來的自己對話,其中有詳細的說明。
本日所有程式碼可參考gt-django repo。