В этом руководстве мы создадим продвинутое веб-приложение на Reflex полностью на языке Python, которое будет без проблем работать внутри Colab. Приложение разработано для демонстрации того, как Reflex позволяет осуществлять разработку полного стека без JavaScript, используя только реактивный код Python.
Мы создадим полноценную панель управления для управления заметками, которая будет включать в себя две страницы, взаимодействие с базой данных в реальном времени, фильтрацию, сортировку, аналитику и персонализацию для пользователя.
Проект будет постепенно создаваться из пяти чистых фрагментов, охватывающих настройку, конфигурацию, управление моделями и состоянием, проектирование пользовательского интерфейса и окончательное выполнение. Это даст нам практическое понимание декларативной архитектуры Reflex и системы реактивности.
Шаг 1: настройка рабочей среды и установка Reflex внутри Colab
Мы создаём новый каталог проекта и убеждаемся, что фреймворк готов к использованию. Мы подготавливаем базовую среду, чтобы наше приложение могло работать без проблем позже, без проблем с зависимостями.
«`python
import os, subprocess, sys, pathlib
APP = «reflexcolabadvanced»
os.makedirs(APP, exist_ok=True)
os.chdir(APP)
subprocess.run([sys.executable, «-m», «pip», «install», «-q», «reflex==0.5.9»])
«`
Шаг 2: определение конфигурационного файла
Мы определяем конфигурационный файл, в котором задаём имя приложения и подключение к базе данных. Мы подключаем Reflex к локальной базе данных SQLite для хранения наших заметок.
«`python
rxconfig = «»»
import reflex as rx
class Config(rx.Config):
appname = «reflexcolab_advanced»
db_url = «sqlite:///reflex.db»
config = Config()
«»»
pathlib.Path(«rxconfig.py»).write_text(rxconfig)
«`
Шаг 3: определение модели данных и класса реактивного состояния
Мы определяем модель данных Note и класс реактивного состояния State, который управляет вводом данных пользователем, фильтрацией и операциями с базой данных.
«`python
app_py = «»»
import reflex as rx
class Note(rx.Model, table=True):
content: str
tag: str = «general»
done: bool = False
class State(rx.State):
user: str = «»
search: str = «»
tag_filter: str = «all»
sort_desc: bool = True
new_content: str = «»
new_tag: str = «general»
toast_msg: str = «»
def set_user(self, v: str): self.user = v
def set_search(self, v: str): self.search = v
def settagfilter(self, v: str): self.tag_filter = v
def setnewcontent(self, v: str): self.new_content = v
def setnewtag(self, v: str): self.new_tag = v
def togglesort(self): self.sortdesc = not self.sort_desc
async def add_note(self):
if self.new_content.strip():
await Note.create(content=self.newcontent.strip(), tag=self.newtag.strip() or «general»)
self.newcontent = «»; self.toastmsg = «Note added»
async def toggledone(self, noteid: int):
note = await Note.get(id=note_id)
if note:
await note.update(done=not note.done)
async def deletenote(self, noteid: int):
await Note.delete(id=note_id)
self.toast_msg = «Deleted»
async def clear_done(self):
items = await Note.all()
for n in items:
if n.done:
await Note.delete(id=n.id)
self.toast_msg = «Cleared done notes»
async def notes_filtered(self):
items = await Note.all()
q = self.search.lower()
if q:
items = [n for n in items if q in n.content.lower() or q in n.tag.lower()]
if self.tag_filter != «all»:
items = [n for n in items if n.tag == self.tag_filter]
items.sort(key=lambda n: n.id, reverse=self.sort_desc)
return items
async def stats(self):
items = await Note.all()
total = len(items)
done = len([n for n in items if n.done])
tags = {}
for n in items:
tags[n.tag] = tags.get(n.tag, 0) + 1
top_tags = sorted(tags.items(), key=lambda x: x[1], reverse=True)[:5]
return {«total»: total, «done»: done, «pending»: total — done, «tags»: top_tags}
«»»
«`
Шаг 4: проектирование модульных компонентов пользовательского интерфейса
Мы проектируем модульные компоненты пользовательского интерфейса, включая боковую панель, теги-фильтры и отдельные строки заметок.
«`python
app_py += «»»
def sidebar():
return rx.vstack(
rx.heading(«RC Advanced», size=»6″),
rx.link(«Dashboard», href=»/»),
rx.link(«Notes Board», href=»/board»),
rx.text(«User»),
rx.input(placeholder=»your name», value=State.user, onchange=State.setuser),
spacing=»3″, width=»15rem», padding=»1rem», border_right=»1px solid #eee»
)
async def stats_cards():
s = await State.stats()
return rx.hstack(
rx.box(rx.text(«Total»), rx.heading(str(s[«total»]), size=»5″), padding=»1rem», border=»1px solid #eee», border_radius=»0.5rem»),
rx.box(rx.text(«Done»), rx.heading(str(s[«done»]), size=»5″), padding=»1rem», border=»1px solid #eee», border_radius=»0.5rem»),
rx.box(rx.text(«Pending»), rx.heading(str(s[«pending»]), size=»5″), padding=»1rem», border=»1px solid #eee», border_radius=»0.5rem»),
spacing=»4″
)
def tag_pill(tag: str, count: int = 0):
return rx.badge(
f»{tag} ({count})» if count else tag,
onclick=State.settag_filter(tag),
cursor=»pointer»,
colorscheme=»blue» if tag == State.tagfilter else «gray»
)
async def tags_bar():
s = await State.stats()
tags = [(«all», s[«total»])] + s[«tags»]
return rx.hstack(*[tag_pill(t[0], t[1]) for t in tags], spacing=»2″, wrap=»wrap»)
def note_row(note: Note):
return rx.hstack(
rx.hstack(
rx.checkbox(ischecked=note.done, onchange=State.toggle_done(note.id)),
rx.text(note.content, text_decoration=»line-through» if note.done else «none»),
),
rx.badge(note.tag, color_scheme=»green»),
rx.button(«», onclick=State.deletenote(note.id), color_scheme=»red», size=»1″),
justify=»between», width=»100%»
)
async def notes_list():
items = await State.notes_filtered()
return rx.vstack(*[note_row(n) for n in items], spacing=»2″, width=»100%»)
«»»
«`
Шаг 5: сборка страниц панели управления и доски заметок
Мы собираем страницы панели управления и доски заметок и компилируем всё приложение Reflex. Мы добавляем навигацию, поля ввода, кнопки и живую статистику для создания полностью интерактивного интерфейса.
«`python
app_py += «»»
def dashboard_page():
return rx.hstack(
sidebar(),
rx.box(
rx.heading(«Dashboard», size=»8″),
rx.cond(State.user != «», rx.text(f»Hi {State.user}, here is your activity»)),
rx.vstack(
rx.suspense(stats_cards, fallback=rx.text(«Loading stats…»)),
rx.suspense(tags_bar, fallback=rx.text(«Loading tags…»)),
spacing=»4″
),
padding=»2rem», width=»100%»
),
width=»100%»
)
def board_page():
return rx.hstack(
sidebar(),
rx.box(
rx.heading(«Notes Board», size=»8″),
rx.hstack(
rx.input(placeholder=»search…», value=State.search, onchange=State.setsearch, width=»50%»),
rx.button(«Toggle sort», onclick=State.togglesort),
rx.button(«Clear done», onclick=State.cleardone, color_scheme=»red»),
spacing=»2″
),
rx.hstack(
rx.input(placeholder=»note content», value=State.newcontent, onchange=State.setnewcontent, width=»60%»),
rx.input(placeholder=»tag», value=State.newtag, onchange=State.setnewtag, width=»20%»),
rx.button(«Add», onclick=State.addnote),
spacing=»2″
),
rx.cond(State.toastmsg != «», rx.callout(State.toastmsg, icon=»info»)),
rx.suspense(notes_list, fallback=rx.text(«Loading notes…»)),
padding=»2rem», width=»100%»
),
width=»100%»
)
app = rx.App()
app.addpage(dashboardpage, route=»/», title=»RC Dashboard»)
app.addpage(boardpage, route=»/board», title=»Notes Board»)
app.compile()
«»»
pathlib.Path(«app.py»).writetext(apppy)
subprocess.run([«reflex», «run», «—env», «prod», «—backend-only»], check=False)
«`
Заключение
Мы разработали и запустили полнофункциональное приложение Reflex, которое объединяет логику с состоянием, динамические компоненты и постоянную базу данных SQLite, и всё это на языке Python. Мы увидели, как легко можно определить поведение фронтенда и бэкенда, используя унифицированный реактивный фреймворк.
1. Какие преимущества даёт использование Reflex для разработки веб-приложений на Python?
Использование Reflex для разработки веб-приложений на Python позволяет осуществлять разработку полного стека без JavaScript, используя только реактивный код Python. Это упрощает процесс разработки и позволяет создавать более эффективные и надёжные приложения.
2. Какие шаги необходимо выполнить для создания продвинутого многостраничного веб-приложения с использованием Reflex?
Для создания продвинутого многостраничного веб-приложения с использованием Reflex необходимо выполнить следующие шаги:
* настроить рабочую среду и установить Reflex внутри Colab;
* определить конфигурационный файл, в котором задаём имя приложения и подключение к базе данных;
* определить модель данных и класс реактивного состояния;
* спроектировать модульные компоненты пользовательского интерфейса;
* собрать страницы панели управления и доски заметок и скомпилировать всё приложение Reflex.
3. Какие компоненты включает в себя пользовательский интерфейс созданного веб-приложения?
Пользовательский интерфейс созданного веб-приложения включает в себя:
* боковую панель;
* теги-фильтры;
* отдельные строки заметок;
* поля ввода;
* кнопки;
* живую статистику.
4. Какие возможности предоставляет панель управления созданного веб-приложения?
Панель управления созданного веб-приложения предоставляет следующие возможности:
* фильтрацию и сортировку заметок;
* добавление новых заметок;
* изменение статуса заметок (выполнено/не выполнено);
* удаление заметок;
* очистку выполненных заметок;
* отображение статистики по количеству заметок, выполненных и невыполненных задач, а также наиболее популярных тегов.
5. Какие инструменты и библиотеки используются для создания веб-приложения?
Для создания веб-приложения используются следующие инструменты и библиотеки:
* Reflex — реактивный фреймворк для разработки веб-приложений на Python;
* SQLite — локальная база данных для хранения заметок;
* pathlib — модуль для работы с путями к файлам и папкам;
* subprocess — модуль для запуска команд в командной строке;
* sys — модуль для работы с системными переменными и аргументами командной строки;
* rxconfig — конфигурационный файл для настройки приложения.