Colab-IDE : reflex==0.2.0
https://github.com/milochen0418/pynecone-colab-ide

https://github.com/reflex-playground/reflex-community-examples 有 IoT

Slido 發問可以在這裡,不好意思問一可以在 slido 上問
或是直接麥克風打斷問都 okay
https://app.sli.do/event/8JwhfE6tHhyfhUzgmz94oa

Kaohsiung.py Reflex 演講

https://hackmd.io/@milochen0418/HJcaPehtn

Reflex (前名為Pynecone) ,讓你可直接Python單一語言開發全端應用
本日演講目標以 Reflex==0.2.0 為來 (Reflex 0.3.0 未來一個月內將可能釋出)

Reflex 的開發

可以使用 VSCode+conda, VSCode+poetry 等方式來開發,或是初次使用的話可以考慮 Pynecone (Reflex) Colab-IDE

Pynecone 改名至 Reflex

What is pynecone(Reflex)

Pinecone -> Pynecone 松果
-> Reflex

pure pyhon 寫 全端網站 (後端、前端)

  • ReactJS

PyQt
flask + jQuery MySQL , PostgreSQL
ReactJS
.NET framework

前端 React

2023 Q1 top 1 最熱的開源新創項目 YC seed
https://github.com/pynecone-io/pynecone

開發上可以參考的資源
目前 colab IDE 直接支持reflex 0.2.0, 但需要自己設key
https://github.com/milochen0418/pynecone-colab-ide

Reflex 架構簡介

很簡化的來說,就是透過開發團隊的努力,將FastAPI + React 的集成,最終包出一個簡易好用的WebApp框架給你用, 希望讓人們可以用純python 來發展WebApp

後端的部份

簡單來說就是 FastAPI ,但是實戰app開發中,它框架已經作了簡化,因此你不用處理到中間複雜的溝通過程。

前端的部份

前端使用 ReactJS (或是說NextJS)
在作畫面調整的部份部份,支持 TailwindCSS, ChakraUI,而且另一個特好用的優點,你可以自己使用其它React元件 來擴充。Reflex願景是希望可以盡可能將React的優點拿來使用。

目前,Netflix、Uber、星巴克或 Twitch 使用了NextJS

NextJS是基於React的框架,差別在於 ReactJS 是在 browser 上直接作了渲染,而 Next.js將渲染方面的工作移到了服務器上,因此客戶端不需要處理這些信息。這提高了性能和SEO,因為服務器預先渲染頁面,然後將最終的HTML發送給客戶端,從而使JS最小化,也就是說加載的代碼更少。不僅用戶可以期待一個更快的網站,而且爬蟲也可以更容易地看到你的網站,並對其進行相應的索引。

Pynecone的渲染到底是 NextJS的哪種呢?

NextJS它支持三種渲染方式包括
客戶端渲染 BSR (Broswer Side Render), 靜態頁面生成 SSG (Static Site Generation), 服務端渲染 SSR (Server Side Render)
pynecone 使用 SSGbun-runtime 來作,因為渲染效能比 NodeJS 快約三倍以上。
其餘渲染知識請見此

實戰開發

申請 key 的部份

ngrok auth token

openai key

開始開發

讓我們來寫寫看一個 DALL-E

建立初始專案

mkdir mydalle cd mydalle reflex init reflex run

新增requirments.txt (Optional)

reflex==0.2.0 openai

簡化成 HelloWorld

"""Welcome to Reflex! This file outlines the steps to create a basic app.""" import reflex as rx import openai import os class State(rx.State): """The app state.""" pass def index() -> rx.Component: return rx.center( rx.heading("Hello World"), ) # Add state and page to the app. app = rx.App(state=State) app.add_page(index, title="MyDALL-E") app.compile()

Layout

import reflex as rx import openai import os openai.api_key = os.environ.get("OPENAI_KEY","YOUR_OPENAI_KEY") class State(rx.State): """The app state.""" image_url = "" image_processing = False image_made = False def get_dalle_result(self, form_data: dict[str, str]): pass pass def index() -> rx.Component: return rx.center( rx.vstack( rx.heading("DALL-E", font_size="1.5em"), rx.form( rx.input(id="prompt_text", placeholder="Enter a prompt.."), rx.button( "Generate Image", type_="submit", width="100%", ), on_submit=State.get_dalle_result, ), rx.divider(), rx.cond( State.image_processing, rx.circular_progress(is_indeterminate=True), rx.cond( State.image_made, rx.image( src=State.image_url, height="25em", width="25em", ), ), ), bg="white", padding="2em", shadow="lg", border_radius="lg", ), width="100%", height="100vh", background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)", ) # Add state and page to the app. app = rx.App(state=State) app.add_page(index, title="MyDALL-E App") app.compile()

完成

import reflex as rx import openai import os openai.api_key = os.environ.get("OPENAI_KEY","YOUR_OPENAI_KEY") class State(rx.State): """The app state.""" image_url = "" image_processing = False image_made = False def get_dalle_result(self, form_data: dict[str, str]): prompt_text:str = form_data['prompt_text'] self.image_processing = True yield try: response = openai.Image.create(prompt=prompt_text, n=1, size="1024x1024") self.image_url = response["data"][0]["url"] self.image_processing = False self.image_made = True yield except: self.image_processing = False yield rx.window_alert("Error to call openAI API") pass def index() -> rx.Component: return rx.center( rx.vstack( rx.heading("DALL-E", font_size="1.5em"), rx.form( rx.input(id="prompt_text", placeholder="Enter a prompt.."), rx.button( "Generate Image", type_="submit", width="100%", ), on_submit=State.get_dalle_result, ), rx.divider(), ## rx.cond( Treu/False, True:作啥layout, False:作啥layout ) rx.cond( State.image_processing, rx.circular_progress(is_indeterminate=True), rx.cond( State.image_made, rx.image( src=State.image_url, height="25em", width="25em", ), ), ), bg="white", padding="2em", shadow="lg", border_radius="lg", ), width="100%", height="100vh", background="radial-gradient(circle at 22% 11%,rgba(62, 180, 137,.20),hsla(0,0%,100%,0) 19%),radial-gradient(circle at 82% 25%,rgba(33,150,243,.18),hsla(0,0%,100%,0) 35%),radial-gradient(circle at 25% 61%,rgba(250, 128, 114, .28),hsla(0,0%,100%,0) 55%)", ) # Add state and page to the app. app = rx.App(state=State) app.add_page(index, title="MyDALL-E App") app.compile()
Select a repo