R

ReflexKR

Reflex-Dokumentation

Full-Stack-Webentwicklung mit Python und Reflex

·

Kursüberblick

1

Reflex kennenlernen und Umgebung einrichten

2

Die Oberfläche mit Komponenten zeichnen

3

State und Vars: Daten zeichnen die Oberfläche

4

Events und Formulare: Kunden hinzufügen

5

Daten aufbereiten und Diagramme

6

Zusammenfassung, Debugging und nächste Schritte

·

Anhang

Full-Stack-Webentwicklung mit Python und Reflex
Lektion 5

Zeit 3:05–3:45

Daten aufbereiten und Diagramme

Am Ende dieser Lektion gibt es unten in der Karte ein horizontales Balkendiagramm mit der Anzahl der Kunden pro Geschlecht, und jedes Mal, wenn du einen Kunden hinzufügst, wächst der passende Balken. Das ist das Grundmuster jedes Daten-Dashboards: Daten in Python aufbereiten und auf der Oberfläche anzeigen.

5-1. Welche Datenform das Diagramm erwartet (5 Min.)

Recharts (eine React-Diagrammbibliothek, die Reflex für dich einbindet) erwartet eine Liste von Dictionaries. Ein Dictionary entspricht einem Balken.

# Daten, die wir haben              # Daten, die das Diagramm braucht
[User(..., gender="Male"),          [{"name": "Male",   "value": 1},
 User(..., gender="Female")]   →    {"name": "Female", "value": 1}]

Bevor wir das Diagramm zeichnen, brauchen wir also einen Schritt zum Aufbereiten (Aggregieren).

5-2. Mit Counter zählen (10 Min.)

from collections import Counter


class State(rx.State):
    users: list[User] = [...]
    users_for_graph: list[dict] = []           # Daten für das Diagramm
    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 gehört zur Python-Standardbibliothek: Counter(["Male", "Female", "Male"]) → {"Male": 2, "Female": 1}.
  • Handler sind echtes Python auf dem Server, also kannst du die Standardbibliothek oder auch pandas ganz normal verwenden. In einer Oberflächen-Funktion wäre das nicht möglich (siehe die Tabelle in Lektion 3).

5-3. Wann aufbereiten? on_load und Aufruf im Handler (5 Min.)

Der Anfangswert von users_for_graph ist eine leere Liste. Gefüllt werden muss sie zu zwei Zeitpunkten.

Beim Öffnen der Seite: Du registrierst den Handler bei on_load in add_page.

app.add_page(
    index,
    title="Customer Data App",
    description="A simple app to manage customer data.",
    on_load=State.transform_data,    # läuft bei jedem Aufruf und Neuladen der Seite
)

Beim Hinzufügen eines Kunden: Du rufst ihn direkt in add_user auf.

@rx.event
def add_user(self, form_data: dict):
    self.users.append(User(**form_data))
    self.transform_data()                 # Diagrammdaten neu berechnen
    self.add_user_dialog_open = False
  • description ist die Seitenbeschreibung (Meta-Tag), die Suchmaschinen und Link-Vorschauen anzeigen.
  • Die Schwäche dieses Ansatzes: Überall, wo du users änderst, darfst du den Aufruf von transform_data() nicht vergessen. Baust du später eine Löschfunktion ein und vergisst ihn, passen Diagramm und Tabelle nicht mehr zusammen.

5-4. Der bessere Weg: Computed Var (5 Min.)

Mit @rx.var deklarierst du einen „Wert, der aus anderem State berechnet wird“. Immer wenn sich users ändert, berechnet Reflex ihn selbstständig neu.

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

    @rx.var
    def users_for_graph(self) -> list[dict]:     # Annotation des Rückgabetyps ist Pflicht
        counts = Counter(user.gender for user in self.users)
        return [{"name": g, "value": c} for g, c in counts.items()]
  • Damit kannst du transform_data, on_load und den Aufruf in add_user komplett streichen. Der Oberflächen-Code (data=State.users_for_graph) bleibt gleich.
  • Der Originalcode verwendet den Event-Ansatz. Im Kurs bringen wir das Diagramm bis 5-5 zunächst auf die ursprüngliche Weise zum Laufen und bauen es in 5-6 gemeinsam auf eine Computed Var um.

Hinweis für Lehrende — „Einen Wert speichern und jedes Mal aktualisieren“ vs. „die Berechnung deklarieren“. Der Vergleich mit Excel kommt gut an: Werte direkt eintippen oder eine Formel (=ZÄHLENWENN(...)) hinterlegen.

5-5. Das Balkendiagramm zeichnen (10 Min.)

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},
    )

Auch ein Diagramm ist eine Komponente: Die Bauteile kommen als Kinder hinein, Daten und Größe übergibst du als Keyword-Argumente.

BauteilAufgabeWichtige Argumente
bar_chartRahmen des gesamten Diagrammsdata (Liste von Dictionaries), layout="vertical" (horizontale Balken)
cartesian_gridGitterlinien im Hintergrundhorizontal=False (nur senkrechte Linien), stroke_dasharray="3 3" (gestrichelt)
x_axisWaagerechte Achse = Anzahl Kundentype_="number", allow_decimals=False (keine Teilstriche wie 1,5 Kunden), domain=[0, "dataMax + 1"] (1 Einheit Luft über dem Maximum)
y_axisSenkrechte Achse = Geschlechttype_="category", data_key="name" (welcher Schlüssel des Dictionaries als Bezeichnung dient)
barBalkendata_key="value" (Schlüssel für die Länge), radius=[0, 6, 6, 0] (Ecken oben links, oben rechts, unten rechts, unten links: nur das Ende abrunden)
  • Bei layout="vertical" ist die x-Achse numerisch und die y-Achse kategorisch. Bei senkrechten Balken (Standard) ist es umgekehrt, deshalb verwechselt man das am häufigsten.
  • rx.color("accent", 9) ist die Akzentfarbe des Themes. Änderst du sie in rxconfig.py, etwa mit RadixThemesPlugin(theme=rx.theme(accent_color="indigo")), ändern sich Buttons und Balken gemeinsam.
  • Die fertige graph() kommt zusammen mit einer Überschrift als drittes Kind in die Karte.
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",
),

Im Browser prüfen — Unter der Tabelle erscheint der Bereich „Audience breakdown“, und die Balken für Male und Female reichen jeweils bis 1. Dass die x-Achse bis 2 geht, liegt an domain=[0, "dataMax + 1"]. Die Balken werden mit einer Animation von links aufgebaut, warte also 1~2 Sekunden.

localhost:3000

Ausprobieren

Customers

2

Your customer directory and audience breakdown.

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

Audience breakdown

Customers by gender

Lektion 5 fertig: Fügst du einen Kunden hinzu, wächst das Balkendiagramm nach Geschlecht mit.

Fügst du in der Vorschau oben einen Kunden mit Female hinzu, wächst der Female-Balken auf 2, und die x-Achse reicht bis 3. Bleibt das Diagramm unverändert, prüfst du den Aufruf self.transform_data() in add_user.

5-6. Selbst ausprobieren: Umbau auf eine Computed Var (5 Min.)

Wenn bis 5-5 alles läuft, stellst du den Event-Ansatz auf eine Computed Var um, ohne die Oberfläche anzufassen. Dafür änderst du drei Stellen:

  1. Lösche in State das Feld users_for_graph: list[dict] = [] und die Methode transform_data, und füge die @rx.var-Methode aus 5-4 ein. Weil die Namen gleich sind, musst du das Feld unbedingt entfernen.
  2. Lösche in add_user die Zeile self.transform_data().
  3. Lösche in app.add_page das 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      # kein Aufruf von 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.",
)                                              # kein on_load
  • An data=State.users_for_graph in graph() änderst du keinen einzigen Buchstaben. Für die Oberfläche sehen normale State-Variablen und Computed Vars genau gleich aus.
  • from collections import Counter bleibt stehen.

Im Browser prüfen — Nach dem Speichern und dem Hot Reload sieht das Diagramm genauso aus wie in 5-5. Wenn der Balken nach dem Hinzufügen einer Kundin mit Female auf 2 wächst, ist der Umbau gelungen. Dass sich alles aktualisiert, ohne dass du irgendetwas aufrufst, ist der Kern einer Computed Var.

Übungen

  1. Füge rx.recharts.graphing_tooltip() als Kind des Diagramms hinzu, damit beim Überfahren mit der Maus der Wert erscheint.
  2. Lege nach demselben Muster wie in 5-6 eine weitere @rx.var def female_count(self) -> int an und zeige neben der Diagrammüberschrift „Female: N“ an.
  3. Baue ein zweites Diagramm mit der Anzahl der Kunden pro E-Mail-Domain (der Teil nach dem @).

Checkpoint

  • Beim Öffnen der Seite zeigt das Diagramm die Balken Male 1 und Female 1.
  • Fügst du einen Kunden hinzu, wird der passende Balken länger.
  • Du kannst den Unterschied zwischen dem on_load-Ansatz und dem Computed-Var-Ansatz erklären.
  • Auch nach dem Umbau auf eine Computed Var aktualisiert sich das Diagramm, wenn du einen Kunden hinzufügst.

← Zurück

Lektion 4 · Events und Formulare: Kunden hinzufügen

Weiter →

Lektion 6 · Zusammenfassung, Debugging und nächste Schritte

Über neue Lektionen informiert werden

Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.

Erhoben: deine E-Mail-Adresse · Zweck: Hinweise auf neue Lektionen oder den Start dieses Kurses · Speicherdauer: bis du die Löschung verlangst. Keine andere Nutzung, keine Weitergabe. Antworte einfach auf eine Benachrichtigung, dann löschen wir sie sofort.

Fragen & Antworten

Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.

Wird als reiner Text angezeigt, ohne Links oder Formatierung.

R

ReflexKR

Python und Reflex zum Anfassen. Alle Beispiele wurden mit Reflex 0.10.0 ausgeführt und geprüft.

ReflexKR ist kostenlos und ohne Werbebanner. Wenn es dir geholfen hat, kannst du es mit einem Kaffee unterstützen. ☕ Spendier uns einen Kaffee

Hinweis zu Affiliate-Links
한국어English日本語简体中文EspañolDeutsch

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

Built with Reflex