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
tutorial_261019/tutorial_261019.py)import dataclasses
from collections import Counter
import reflex as rx
@dataclasses.dataclass
class User:
name: str
email: str
gender: str
class State(rx.State):
users: list[User] = [
User(name="Danilo Sousa", email="danilo@example.com", gender="Male"),
User(name="Zahra Ambessa", email="zahra@example.com", gender="Female"),
]
users_for_graph: list[dict] = []
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.transform_data()
self.add_user_dialog_open = 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()
]
def show_user(user: User):
return rx.table.row(
rx.table.cell(user.name),
rx.table.cell(user.email),
rx.table.cell(user.gender),
style={"_hover": {"bg": rx.color("gray", 3)}},
align="center",
)
def add_customer_button() -> rx.Component:
return rx.dialog.root(
rx.dialog.trigger(
rx.button(
rx.icon("plus", size=18),
rx.text("Add User", size="2"),
),
),
rx.dialog.content(
rx.dialog.title(
"Add New User",
),
rx.dialog.description(
"Fill the form with the user's info",
),
rx.form(
rx.flex(
rx.input(placeholder="User Name", name="name", required=True),
rx.input(
placeholder="user@reflex.dev",
name="email",
),
rx.select(
["Male", "Female"],
placeholder="Select gender",
default_value="Male",
name="gender",
custom_attrs={"aria-label": "Gender"},
),
rx.flex(
rx.dialog.close(
rx.button(
"Cancel",
type="button",
variant="soft",
color_scheme="gray",
),
),
rx.button("Submit", type="submit"),
spacing="3",
justify="end",
),
direction="column",
spacing="4",
),
on_submit=State.add_user,
reset_on_submit=False,
),
max_width="450px",
),
open=State.add_user_dialog_open,
on_open_change=State.set_add_user_dialog_open,
)
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},
)
def index() -> rx.Component:
return rx.box(
rx.box(
rx.box(
rx.box(
rx.heading("Customers", size="6", as_="h3", margin="0"),
rx.badge(
State.users.length(),
variant="soft",
color_scheme="gray",
radius="full",
),
display="flex",
align_items="center",
gap="12px",
),
rx.text(
"Your customer directory and audience breakdown.",
size="2",
color=rx.color("slate", 11),
margin_top="6px",
),
),
add_customer_button(),
display="flex",
align_items="center",
justify_content="space-between",
flex_wrap="wrap",
gap="16px",
padding="24px",
),
rx.box(
rx.table.root(
rx.table.header(
rx.table.row(
rx.table.column_header_cell("Name"),
rx.table.column_header_cell("Email"),
rx.table.column_header_cell("Gender"),
)
),
rx.table.body(rx.foreach(State.users, show_user)),
variant="ghost",
size="3",
width="100%",
),
overflow_x="auto",
width="100%",
border_top=f"1px solid {rx.color('slate', 4)}",
border_bottom=f"1px solid {rx.color('slate', 4)}",
padding_x="12px",
),
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",
),
width="100%",
min_width="0",
max_width="64em",
margin_x="auto",
margin_y="24px",
border=f"1px solid {rx.color('slate', 5)}",
border_radius="16px",
background=rx.color("slate", 1),
overflow="hidden",
box_shadow="0 4px 24px rgba(0, 0, 0, 0.03)",
style={
"& *": {"box_sizing": "border-box"},
"& p, & h3": {"text_align": "left"},
},
)
app = rx.App()
app.add_page(
index,
title="Customer Data App",
description="A simple app to manage customer data.",
on_load=State.transform_data,
)| Begriff | Bedeutung |
|---|---|
| Full Stack | Entwicklung, die sowohl die Oberfläche (Frontend) als auch den Server (Backend) umfasst |
| Komponente | Ein Baustein der Oberfläche. In Reflex ein einzelner Funktionsaufruf rx.xxx(...) |
| Props | Einstellungen, die einer Komponente mitgegeben werden. Werden als Keyword-Argumente übergeben |
| State | Klasse mit den Daten und Event-Handlern der App. Existiert auf dem Server pro Session |
| Var | Ein Ausdruck im Oberflächen-Code, der auf eine State-Variable verweist. Der Wert wird im Browser eingesetzt |
| Computed Var | Eine mit @rx.var deklarierte Variable, die aus anderem State berechnet wird |
| Event-Handler | Eine State-Methode mit @rx.event. Läuft als Reaktion auf Nutzeraktionen auf dem Server |
| Kontrollierte Komponente | Ein Muster, bei dem der State den Wert bzw. Zustand eines Elements bestimmt (open=, value=) |
| Compile-Zeit | Der Moment beim Start der App, in dem Oberflächen-Funktionen in React-Code übersetzt werden |
| Laufzeit | Die Phase, in der die App läuft und Nutzer mit ihr interagieren. Hier werden Event-Handler ausgeführt |
| WebSocket | Ein Kommunikationsverfahren, bei dem Browser und Server eine Verbindung offen halten und in beide Richtungen Nachrichten austauschen |
| Hot Reload | Beim Speichern wird der Code automatisch neu kompiliert und übernommen, ohne den Server neu zu starten |
Wenn du jede Lektion in einen eigenen Artikel überträgst, entsteht eine Serie aus 6 Teilen.
| Teil | Beispieltitel | Lektion |
|---|---|---|
| 1 | Web-Apps nur mit Python: Einstieg in Reflex (+ Windows-Fehler beheben) | Lektion 1 |
| 2 | Oberflächen ohne HTML: Komponenten und Styles in Reflex | Lektion 2 |
| 3 | Warum len() in Reflex nicht funktioniert: State und Vars | Lektion 3 |
| 4 | Daten über Formulare und Dialoge hinzufügen | Lektion 4 |
| 5 | Mit Python aggregieren und Diagramme zeichnen | Lektion 5 |
| 6 | 8 Fehler, auf die jeder Reflex-Einsteiger stößt | Lektion 6, Abschnitt 6-2 |
Hinweis für Lehrende schreibst du als Fließtext aus oder machst daraus einen „Tipp“-Kasten.len()-Fehler aus Lektion 3, das fehlende type am Cancel-Button und der Dialog, der sich nicht schließt, aus Lektion 4 lohnen sich besonders, um sie bewusst nachzustellen.Über neue Lektionen informiert werden
Wir schicken dir eine E-Mail, wenn dieser Kurs neue Lektionen bekommt oder ein Folgekurs erscheint.
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© 2026 ReflexKR · Since 2026 · CC BY-NC 4.0
Fragen & Antworten
Frag alles zu dieser Lektion. Fragen aus allen Sprachversionen dieser Seite erscheinen hier gemeinsam.