R

ReflexKR

Reflex公式ドキュメント

Reflexで始めるPythonフルスタックWeb開発

·

講座の概要

1

Reflexの紹介と開発環境

2

コンポーネントで画面を描く

3

StateとVar:データに画面を描かせる

4

イベントとフォーム:顧客を追加する

5

データ加工とチャート

6

まとめ、デバッグ、次のステップ

·

付録

Reflexで始めるPythonフルスタックWeb開発
5限目

時間 3:05–3:45

データ加工とチャート

この時限を終えると、カードの下部に性別ごとの顧客数を示す横棒グラフが表示され、顧客を追加するたびに棒が伸びるようになります。Pythonでデータを加工して画面に表示する、データダッシュボードの基本パターンです。

5-1. チャートが求めるデータの形 (5分)

Recharts(Reflexがラップして提供しているReactのチャートライブラリ)は、辞書のリストを受け取ります。辞書1つが棒1本に対応します。

# 手元にあるデータ                   # チャートが求めるデータ
[User(..., gender="Male"),          [{"name": "Male",   "value": 1},
 User(..., gender="Female")]   →    {"name": "Female", "value": 1}]

そのため、チャートを描く前に加工(集計)のステップが必要です。

5-2. Counterで集計する (10分)

from collections import Counter


class State(rx.State):
    users: list[User] = [...]
    users_for_graph: list[dict] = []           # チャート用のデータ
    add_user_dialog_open: bool = False

    @rx.event
    def transform_data(self):
        gender_counts = Counter(user.gender for user in self.users)
        self.users_for_graph = [
            {"name": gender_group, "value": count}
            for gender_group, count in gender_counts.items()
        ]
  • CounterはPythonの標準ライブラリです。Counter(["Male", "Female", "Male"]) → {"Male": 2, "Female": 1}。
  • ハンドラはサーバーで動く本物のPythonなので、標準ライブラリでもpandasでもそのまま使えます。画面の関数の中ではできないことです(3限目の表)。

5-3. いつ加工するか:on_loadとハンドラ内での呼び出し (5分)

users_for_graphの初期値は空のリストです。2つのタイミングでデータを入れる必要があります。

ページを開いたとき:add_pageのon_loadにハンドラを登録します。

app.add_page(
    index,
    title="Customer Data App",
    description="A simple app to manage customer data.",
    on_load=State.transform_data,    # ページを開くたび・再読み込みのたびに実行
)

顧客を追加したとき:add_userの中から直接呼び出します。

@rx.event
def add_user(self, form_data: dict):
    self.users.append(User(**form_data))
    self.transform_data()                 # チャートのデータを再計算
    self.add_user_dialog_open = False
  • descriptionは、検索エンジンやリンクのプレビューに表示されるページの説明(metaタグ)です。
  • この方法の弱点は、usersを変更するすべての場所でtransform_data()を忘れずに呼び出さなければならないことです。削除機能を追加するときに呼び出しを忘れると、チャートとテーブルの内容がずれてしまいます。

5-4. もっと良い方法:computed var (5分)

@rx.varを付けると、「ほかの状態から計算される値」を宣言できます。usersが変わるたびに、Reflexが自動的に再計算してくれます。

class State(rx.State):
    users: list[User] = [...]

    @rx.var
    def users_for_graph(self) -> list[dict]:     # 戻り値の型アノテーションは必須
        counts = Counter(user.gender for user in self.users)
        return [{"name": g, "value": c} for g, c in counts.items()]
  • こうすれば、transform_data、on_load、add_user内の呼び出しをすべて削除できます。画面のコード(data=State.users_for_graph)はそのままです。
  • 元のコードはイベント方式を使っています。講座では5-5まで元の方式でチャートを表示し、5-6でみんなでcomputed varにリファクタリングします。

講師メモ — 「値を保存しておいて毎回更新する」か、「計算方法を宣言する」か。Excelでセルに値を直接入力するのと、数式(=COUNTIF(...))を入れるのとの違いにたとえると、よく伝わります。

5-5. 棒グラフを描く (10分)

def graph():
    return rx.recharts.bar_chart(
        rx.recharts.cartesian_grid(
            horizontal=False, stroke_dasharray="3 3", stroke=rx.color("slate", 4)
        ),
        rx.recharts.x_axis(
            type_="number",
            allow_decimals=False,
            axis_line=False,
            tick_line=False,
            domain=[0, "dataMax + 1"],
        ),
        rx.recharts.y_axis(
            type_="category",
            data_key="name",
            axis_line=False,
            tick_line=False,
            width=64,
        ),
        rx.recharts.bar(
            data_key="value",
            fill=rx.color("accent", 9),
            radius=[0, 6, 6, 0],
            bar_size=28,
        ),
        data=State.users_for_graph,
        layout="vertical",
        width="100%",
        height=160,
        margin={"top": 0, "right": 16, "bottom": 0, "left": 0},
    )

チャートもコンポーネントです。部品を子要素として入れ、データやサイズはキーワード引数で指定します。

部品役割主な引数
bar_chartチャート全体の枠data(辞書のリスト)、layout="vertical"(横棒)
cartesian_grid背景のグリッド線horizontal=False(縦線のみ)、stroke_dasharray="3 3"(点線)
x_axis横軸=顧客数type_="number"、allow_decimals=False(1.5人のような目盛りを防ぐ)、domain=[0, "dataMax + 1"](最大値より1だけ余裕を持たせる)
y_axis縦軸=性別type_="category"、data_key="name"(辞書のどのキーを名前として使うか)
bar棒data_key="value"(長さに使うキー)、radius=[0, 6, 6, 0](左上・右上・右下・左下の角。先端だけを丸める)
  • layout="vertical"のときは、x軸が数値、y軸がカテゴリになります。縦棒(既定値)とは逆なので、いちばん混乱しやすいところです。
  • rx.color("accent", 9)はテーマのアクセントカラーです。rxconfig.pyでRadixThemesPlugin(theme=rx.theme(accent_color="indigo"))のように変えると、ボタンと棒の色が一緒に変わります。
  • 作ったgraph()は、見出しの文言と一緒にカードの3番目の子要素として入れます。
rx.box(
    rx.text("Audience breakdown", size="3", weight="bold"),
    rx.text(
        "Customers by gender",
        size="2",
        color=rx.color("slate", 11),
        margin_top="4px",
        margin_bottom="20px",
    ),
    graph(),
    padding="24px",
),

ブラウザで確認 — テーブルの下に「Audience breakdown」のエリアができ、MaleとFemaleの棒がそれぞれ1まで描かれます。x軸が2まであるのはdomain=[0, "dataMax + 1"]のためです。棒は左から伸びるアニメーションで表示されるので、1~2秒待ってみてください。

localhost:3000

操作してみよう

Customers

2

Your customer directory and audience breakdown.

NameEmailGender
Danilo Sousadanilo@example.comMale
Zahra Ambessazahra@example.comFemale

Audience breakdown

Customers by gender

5限目の完成形:顧客を追加すると、性別ごとの棒グラフも一緒に伸びます。

上のプレビューでFemaleの顧客を1人追加すると、Femaleの棒が2まで伸び、x軸が3まで広がります。チャートが変わらない場合は、add_userの中のself.transform_data()の呼び出しを確認してください。

5-6. やってみよう:computed varにリファクタリング (5分)

5-5までの動作を確認できたら、画面はそのままにして、イベント方式をcomputed varに置き換えます。直すのは3か所です。

  1. Stateからusers_for_graph: list[dict] = []のフィールドとtransform_dataメソッドを削除し、5-4の@rx.varメソッドを追加します。同じ名前が重複するので、フィールドは必ず削除してください。
  2. add_userの中のself.transform_data()の行を削除します。
  3. app.add_pageからon_load=State.transform_dataを削除します。
class State(rx.State):
    users: list[User] = [...]
    add_user_dialog_open: bool = False

    @rx.event
    def set_add_user_dialog_open(self, open_: bool):
        self.add_user_dialog_open = open_

    @rx.event
    def add_user(self, form_data: dict):
        self.users.append(User(**form_data))
        self.add_user_dialog_open = False      # transform_data()の呼び出しなし

    @rx.var
    def users_for_graph(self) -> list[dict]:
        counts = Counter(user.gender for user in self.users)
        return [{"name": g, "value": c} for g, c in counts.items()]


app = rx.App()
app.add_page(
    index,
    title="Customer Data App",
    description="A simple app to manage customer data.",
)                                              # on_loadなし
  • graph()のdata=State.users_for_graphは1文字も変えません。画面側から見ると、ふつうの状態変数もcomputed varも同じように見えます。
  • from collections import Counterはそのまま残します。

ブラウザで確認 — 保存するとホットリロードされ、チャートは5-5とまったく同じように表示されます。Femaleの顧客を追加して棒が2まで伸びれば、リファクタリングは成功です。一度も呼び出していないのに更新される、これがcomputed varの要点です。

演習課題

  1. rx.recharts.graphing_tooltip()をチャートの子要素として追加し、マウスを乗せると値が表示されるようにしてみましょう。
  2. 5-6と同じ方法で@rx.var def female_count(self) -> intをもう1つ作り、チャートの見出しの横に「Female N人」と表示してみましょう。
  3. メールアドレスのドメイン(@より後ろ)ごとの顧客数チャートをもう1つ作ってみましょう。

チェックポイント

  • ページを開くと、チャートにMale 1、Female 1の棒が表示される。
  • 顧客を追加すると、該当する棒が長くなる。
  • on_load方式とcomputed var方式の違いを説明できる。
  • computed varに置き換えたあとも、顧客を追加するとチャートが更新される。

← 前へ

4限目 · イベントとフォーム:顧客を追加する

次へ →

6限目 · まとめ、デバッグ、次のステップ

新しい授業・講座のお知らせを受け取る

この講座に授業が追加されたり、続きの講座が公開されたりしたらメールでお知らせします。

収集項目:メールアドレス・目的:この講座の新しい授業・公開のお知らせ・保有期間:解除のご依頼まで。他の目的には使わず、第三者にも提供しません。お知らせメールに返信いただければすぐに削除します。

質問と回答

この回について気になることを書き込んでください。すべての言語のページの質問がここに集まります。

リンクや書式なしで、そのままの文字で表示されます。

R

ReflexKR

触って学ぶPythonとReflex。すべての例はReflex 0.10.0で実際に動かして確認しています。

ReflexKRはバナー広告なし・無料で運営しています。役に立ったら、コーヒー一杯で応援してください。 ☕ コーヒーで応援する

アフィリエイトと支援について
한국어English日本語简体中文EspañolDeutsch

© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0

Built with Reflex