A webfejlesztés a programozás egyik legnépszerűbb felhasználási módja. A Python a világ egyik legnépszerűbb programozási nyelve. Miért nem tudunk webalkalmazásokat készíteni Pythonban?
A felhasználói felület elkészítésének egyszerűnek kell lennie, de még akkor is, ha nagyszerű mérnökök vannak a csapatban, óriási akadályt jelentett az új nyelvek és eszközök megtanulása. A felhasználói felület létrehozása gyakran nehezebb lehet, mint a tényleges munka! Pontosan ennek a problémának a megoldására építettük a Reflexet, egy nyílt forráskódú Python webes keretrendszert.
A motorháztető alatt a Reflex alkalmazások egy React frontend alkalmazásra és egy FastAPI háttéralkalmazásra fordíthatók. Csak a felhasználói felület van fordítva Javascriptre; az összes alkalmazáslogika és állapotkezelés Pythonban marad, és a szerveren fut. A Reflex a WebSockets segítségével küldi el az eseményeket a frontendről a háttérrendszerre, és küldi az állapotfrissítéseket a háttérrendszerről a frontendre.
Már volt néhány módja annak, hogy Pythonban készítsünk alkalmazásokat, de egyik sem felel meg az igényeinknek.
Egyrészt vannak olyan keretrendszerek, mint a Django és a Flask , amelyek kiválóan alkalmasak éles szintű webalkalmazások készítésére. De csak a háttérrendszert kezelik – továbbra is JavaScriptet és frontend keretrendszert kell használnia, valamint sok feldolgozási kódot kell írnia a frontend és a háttérrendszer összekapcsolásához.
Másrészt a tiszta Python-könyvtárak, mint például a Dash és a Streamlit, nagyszerűek lehetnek kis projektekhez, de egy adott használati esetre korlátozódnak, és nem rendelkeznek a teljes webalkalmazás létrehozásához szükséges funkciókkal és teljesítménnyel. Ahogy alkalmazásának funkciói és összetettsége bővül, előfordulhat, hogy eléri a keretrendszer korlátait, ekkor vagy korlátoznia kell az ötletét, hogy illeszkedjen a keretrendszerhez, vagy le kell vetnie a projektet, és újjá kell építenie egy "valódi webes keretrendszer" segítségével.
Ezt a szakadékot egy olyan keretrendszer létrehozásával szeretnénk áthidalni, amely könnyen és intuitív módon kezdhető el, ugyanakkor rugalmas és hatékony marad bármely alkalmazás támogatásához.
Most pedig nézzük meg, hogyan építettük fel a Reflexet e célok elérése érdekében.
A full-stack webalkalmazások előtérből és háttérrendszerből állnak. A frontend a felhasználói felület, és a felhasználó böngészőjében futó weboldalként szolgál. A háttérrendszer kezeli a logikát és az állapotkezelést (például adatbázisok és API-k), és egy kiszolgálón fut. A hagyományos webfejlesztésben ez általában két különálló alkalmazás, és gyakran különböző keretrendszerben vagy nyelven íródnak. Például kombinálhat egy Flask hátteret egy React előtérrel. Ezzel a megközelítéssel két különálló alkalmazást kell karbantartania, és sok általános kódot kell írnia az előtér és a háttérrendszer összekapcsolásához.
Szeretnénk egyszerűsíteni ezt a folyamatot a Reflexben azáltal, hogy a frontendet és a backendet is egyetlen kódbázisban határozzuk meg, miközben mindenhez Pythont használunk. A fejlesztőknek csak az alkalmazás logikája miatt kell aggódniuk, nem pedig az alacsony szintű megvalósítás részletei miatt.
Azt akarjuk, hogy a Reflex alkalmazások hagyományos webalkalmazásnak tűnjenek és úgy érezzék a végfelhasználó számára, hogy a fejlesztők továbbra is könnyen elkészíthetők és karbantarthatók legyenek. Ennek érdekében kiforrott és népszerű webes technológiákra építettünk.
Amikor reflex run
az alkalmazást, a Reflex lefordítja a kezelőfelületet egy egyoldalas Next.js alkalmazásba, és egy porton (alapértelmezés szerint 3000
) szolgálja ki, amelyhez hozzáférhet a böngészőben.
A frontend feladata, hogy tükrözze az alkalmazás állapotát, és eseményeket küldjön a háttérrendszernek, amikor a felhasználó interakcióba lép a felhasználói felülettel. A frontenden nem fut tényleges logika.
A Reflex frontendek olyan összetevőkből épülnek fel, amelyek összetett felhasználói felületek létrehozásához összeállíthatók. A HTML-t és Pythont keverő sablonnyelv használata helyett csak Python-függvényeket használunk a felhasználói felület meghatározásához.
A motorháztető alatt az összetevők a React komponensekké állnak össze. Számos alapvető összetevőnk a Radixen , egy népszerű React komponenskönyvtáron alapul. Számos egyéb komponensünk is van grafikus ábrázoláshoz, adattáblázatokhoz és még sok máshoz. Azért választottuk a Reactet, mert ez egy népszerű könyvtár hatalmas ökoszisztémával. Nem az a célunk, hogy újra létrehozzuk a webes ökoszisztémát, hanem hogy elérhetővé tegyük a Python fejlesztők számára.
Ez azt is lehetővé teszi a felhasználók számára, hogy saját komponenseiket hozzák magukkal, ha nincs szükségük alkatrészre. A felhasználók becsomagolhatják saját React-komponenseiket, majd közzétehetik azokat mások számára. Idővel kiépítjük harmadik féltől származó összetevő-ökoszisztémánkat, hogy a felhasználók könnyen megtalálhassák és felhasználhassák a mások által készített összetevőket.
Gondoskodni akartunk arról, hogy a Reflex alkalmazások jól nézzenek ki a dobozból, miközben továbbra is teljes ellenőrzést biztosítunk a fejlesztőknek alkalmazásuk megjelenése felett.
Van egy alapvető témarendszerünk, amely lehetővé teszi magas szintű stílusbeállítások, például sötét mód és kiemelő színek beállítását az egész alkalmazásban, hogy egységes megjelenést és érzetet biztosítson.
Ezen túlmenően a Reflex komponensei a CSS teljes erejével stílusozhatók. Kihasználjuk az Emotion könyvtárat, hogy lehetővé tegyük a "CSS-in-Python" stílust, így bármilyen CSS-propagot átadhat kulcsszó argumentumként egy összetevőnek. Ez magában foglalja a reszponzív kellékeket az értékek listájának átadásával.
A Reflexben csak a frontend fordítja le a Javascriptet, és fut a felhasználó böngészőjén, míg az összes állapot és logika Pythonban marad, és a szerveren fut. reflex run
elindítunk egy FastAPI-kiszolgálót (alapértelmezés szerint a 8000
porton), amelyhez a frontend egy websocketen keresztül csatlakozik.
Minden állapot és logika egy State
belül van meghatározva. Az állam varsokból és eseménykezelőkből áll. A változók bármely olyan értéket jelentenek az alkalmazásban, amely idővel változhat. Ezek osztályattribútumként vannak definiálva a State
osztályban, és bármilyen Python-típus lehet, amely JSON-ba sorozható.
Az eseménykezelők olyan metódusok State
osztályban, amelyek akkor hívódnak meg, amikor a felhasználó interakcióba lép a felhasználói felülettel. Ez az egyetlen módja annak, hogy módosítsuk a Vars-t a Reflexben, és meghívhatók válaszként a felhasználói műveletekre, például egy gombra kattintásra vagy egy szövegdobozba való beírásra.
Mivel az eseménykezelők a háttérben futnak, bármelyik Python-könyvtárat használhatja bennük.
Általában webalkalmazások írásakor sok általános kódot kell írnia az előtér és a háttérrendszer összekapcsolásához. A Reflex segítségével emiatt nem kell aggódnia – mi kezeljük helyette a kommunikációt a frontend és a háttérrendszer között. A fejlesztőknek csak meg kell írniuk az eseménykezelő logikáját, és a változók frissítésekor a felhasználói felület automatikusan frissül.
A felhasználó számos módon kommunikálhat a felhasználói felülettel, például kattinthat egy gombra, beírhat egy szövegmezőt, vagy az egérmutatót egy elem fölé viheti. A Reflexben ezeket eseményindítóknak nevezzük.
A kezelőfelületen eseménysort tartunk fenn az összes függőben lévő eseményből. Egy esemény három fő adatból áll:
Amikor egy esemény aktiválódik, az hozzáadódik a várólistához. Van egy processing
jelzőnk, amely biztosítja, hogy egyszerre csak egy esemény kerüljön feldolgozásra. Ez biztosítja, hogy az állapot mindig konzisztens legyen, és ne legyenek versenyfeltételek, amikor két eseménykezelő egyszerre módosítja az állapotot. Ez alól vannak kivételek, például a háttérben zajló események, amelyek lehetővé teszik az események futtatását a háttérben a felhasználói felület blokkolása nélkül.
Miután az esemény készen áll a feldolgozásra, egy WebSocket kapcsolaton keresztül elküldésre kerül a háttérrendszernek.
Az esemény beérkezése után a rendszer feldolgozza a háttérben. A Reflex állapotkezelőt használ, amely leképezést tart fenn az ügyféljogkivonatok és azok állapota között. Alapértelmezés szerint az állapotkezelő csak egy memórián belüli szótár, de kibővíthető adatbázis vagy gyorsítótár használatára. A termelésben a Redist használjuk állami menedzserként.
Miután megvan a felhasználó állapota, a következő lépés az eseménykezelő futtatása az argumentumokkal.
Minden alkalommal, amikor egy eseménykezelő visszatér (vagy ad eredményt), mentjük az állapotot az állapotkezelőben, és elküldjük az állapotfrissítéseket a kezelőfelületnek a felhasználói felület frissítéséhez. A teljesítmény fenntartása érdekében az állapot növekedésével a Reflex belsőleg nyomon követi az eseménykezelő során frissített változókat ( piszkos vars ).
Amikor az eseménykezelő befejezte a feldolgozást, megtaláljuk az összes piszkos változót, és létrehozunk egy állapotfrissítést, amelyet elküldünk a frontendnek.
Az új állapotot az állapotkezelőnkben tároljuk, majd elküldjük az állapotfrissítést a frontendnek. A frontend ezután frissíti a felhasználói felületet, hogy tükrözze az új állapotot.
Remélem, ez jó áttekintést ad a Reflex működéséről a motorháztető alatt. További bejegyzések jelennek meg, amelyekben megosztjuk, hogyan tettük a Reflexet méretezhetővé és hatékonyan olyan funkciókkal, mint az állapotfelosztás és a fordítóoptimalizálás.