strålar är en WSGI kompatibelt webbramverk utformad för små webbapplikationer. Den stöder både Python 2.7 och Python 3.2. strålar hanterar multibyte-charcters korrekt (Det är viktigt för mig, så jag är en japansk).
Installation
easy_install strålar
eller
PIP installera -e git: //github.com/yuin/rays.git#egg=rays
eller ladda ner en zip-fil från https://github.com/yuin/rays/zipball/master och
Python setup.py installera
Exempel
Du hittar dessa källkoden i src / prover / blogga katalogen.
index.py:
från strålar import *
från rays.compat import *
import sys, os.path, math, contextlib
från datetime importdatetime
import threading
app = Applikation ()
APP_DIR = os.path.dirname (__ file__)
DB_FILE = os.path.join (APP_DIR, "test.db")
c = threading.local ()
app.config ([
& Nbsp; ("debug", sant)
& Nbsp; ("renderaren", {"template_dir": os.path.join (APP_DIR, "mallar"),
& Nbsp; "cache_dir": os.path.join (APP_DIR, "templates / cachar")}),
& Nbsp; ("DatabaseExtension", {"anslutning": DB_FILE, "transaktion": "commit_on_success"}),
& Nbsp; ("SessionExtension", {"butik": "Database", "hemliga": "asdfeE305Gs0lg",
& Nbsp; "cookie_path": "admin"}),
& Nbsp; ("StaticFileExtension", {"url": "statik /", "väg": os.path.join (APP_DIR, "statik")}),
& Nbsp; ("ADMIN_NAME", "admin"),
& Nbsp; ("admin_password", "lösenord"),
& Nbsp; ("blog_title", "Min blogg"),
& Nbsp; ("entry_per_page", 3),
])
klass BaseModel (Model): # {{{
& Nbsp; def class_init (CLS):
& Nbsp; Model.class_init (CLS)
& Nbsp; @ cls.hook ("before_create")
& Nbsp; def before_create (själv):
& Nbsp; self.created_at = datetime.now ()
#}}}
klass Entry (BaseModel): # {{{
& Nbsp; tabellnamn = "poster"
& Nbsp; def validera (själv):
& Nbsp; resultat = []
& Nbsp; om inte self.title: result.append (". Titel krävs")
& Nbsp; om len (self.title)> 100: result.append ("Titel för lång.")
& Nbsp; om len (self.title) <2: result.append (". Titel för kort")
& Nbsp; om inte self.body: result.append (". Body krävs")
& Nbsp; retur resultat
#}}}
# filter {{{
def context_setup_filter (* a, ** k):
& Nbsp; c.title = app.vars.blog_title
& nbsp; c.errors = []
& Nbsp; avkastning
def admin_filter (* a, ** k):
& Nbsp; om inte app.session ["signin"]:
& Nbsp; app.res.redirect (app.url.admin_signin ())
& Nbsp; avkastning
def flash_filter (* a, ** k):
& Nbsp; dir = app.session ["signin"]
& Nbsp; om dir:
& Nbsp; app.session ["flash"] = app.session ["flash"] eller {}
& Nbsp; nycklar = lista (iter_keys (app.session ["flash"]))
& Nbsp; avkastning
& Nbsp; om dir:
& Nbsp; för nyckeln i nycklar: del app.session ["flash"] [tangent]
#}}}
# hjälpare {{{
@ App.helper
@ Contextlib.contextmanager
def main_block (hjälpare):
& Nbsp; helper.concat ("
& Nbsp; med helper.capture ("__ main_block"):
& Nbsp; avkastning
& Nbsp; helper.concat (helper.captured ("__ main_block"))
& Nbsp; helper.concat ("
@ App.helper
def show_errors (hjälpreda, fel):
& Nbsp; om fel:
& Nbsp; helper.concat ("
- ")
- " + error + " ")
& Nbsp; för fel i fel:
& Nbsp; helper.concat ("
& Nbsp; helper.concat ("
@ App.helper
def show_message (hjälpare, meddelande):
& Nbsp; om meddelande:
& Nbsp; helper.concat ("
& Nbsp; helper.concat (meddelande)
& Nbsp; helper.concat ("
@ App.helper
def format_datetime (hjälpare, dt):
& Nbsp; returnera dt.strftime ("..% M% d% y /% I% p% Z") lägre ().
@ App.helper
def hatom_published (hjälpare, post):
& Nbsp; återkomst "" "% s " ""% (entry.created_at.isoformat (), helper.format_datetime (entry.created_at))
@ App.helper
def format_body (hjälpare, kropp):
& Nbsp; retur body.replace (" n", "
")
@ App.helper
def page_link (hjälpreda, sida):
& Nbsp; "? Page =% d" avkastning app.url.index () +% sida
@ App.helper
def sidnumrering (hjälpare, räkna, sida):
& Nbsp; sida = int (sida)
& Nbsp; n = app.vars.entry_per_page
& Nbsp; tpl = ["
- "]
- % s "%
- 1 "% helper.page_link (c, 1))
- & nbsp; & nbsp; ....... & nbsp; & nbsp; ")
- % d "% i)
- % d "% (helper.page_link (c, i), i))
- & nbsp; & nbsp; ...... & nbsp; & nbsp; ")
- % d "% (helper.page_link (c, max_page), max_page))
- % s "%
- Operations:. Enkel men kraftfull
- Rutter definieras av reguljära uttryck och typkonstruerare:
- @ app.get (& quot; ledamot / (int: d +) & quot;)
- def show_member (member_id):
- # ...
- app.url har enkel hänvisning till linjer:
- app.url.show_member (1) # = & gt; & Quot; http: // somehost / medlem / 1 & quot;
- Filter och krokar. Skriva DRY koden
- Krokar kommer att kallas tillbaka på efter krok punkter.
- before_initialize
- after_initialize
- before_call
- before_dispatch
- before_action
- before_start_response
- Krokar exempel:
- @ app.hook (& quot; before_start_response & quot;)
- def status_log_hook (* a):
- om app.res.is_success:
- app.logger.info (& quot; framgång & quot;)
- elif app.res.is_abort:
- app.logger.warn (& quot; abort & quot;)
- annars:
- app.logger.error (& quot; fel:% s & quot;% unicode (app.res.exception))
- Filter möjliggör åtgärder för att köra före och efter bearbetning kod:
- def filtrera (* args):
- # förbehandling
- avkastning
- # efterbearbetning
- med app.filter (filter):
- @ app.get (& quot; ledamot / (int: d +) & quot;)
- def show_member (member_id):
- # ...
- Mallar:. Snabb och flexibel
- Att göra index.html, app.renderer.index (VARS).
- Strängar omgivna av & quot; & quot; kommer att tolkas som en Python kod.
- & lt; % A = 10% & gt;
- & lt; % = Python kod% & gt; kommer att ersättas av resultatet av verkställande & quot; python-kod & quot;.
- applys alltid ett filter (dvs. Cgi.escape). Att stänga av den, använd
- Många sätt att uttrycka block:
- & lt; % - For i in xrange (10): -% & gt;
- & lt; % = Ett% & gt;
- & lt; %% & Gt;
- & lt; % - For i in xrange (10) {: -% & gt;
- & lt; % = Ett% & gt;
- & lt; %:}% & Gt;
- & lt; % - For i in xrange (10): -% & gt;
- & lt; % = Ett% & gt;
- & lt; % End% & gt;
- Integrerade användbar mall hjälpare:
- & lt; % Med h.capture (& quot; body & quot;):% & gt;
- foo
- & lt; %% & Gt;
- & lt; % = Kropps% & gt;
- Orms: Enkel wrapper för inbyggda sqlite3 modul:.
- resultat = app.db.select ([Site, sida], dir = & quot;? Page.site_id = Site.id och Page.id = & quot ;, värden = [1])
- print (resultat [0] .site)
- print (resultat [0] .sid)
- app.db.insert (sida)
- app.db.update (sida)
- app.db.delete (sida)
- app.db.shell () # interaktiv sqlite3 skal
- Sessions:
- @ app.get (& quot; signin & quot;)
- def signin ():
- Om app.req.input [& quot; namn & quot;] == & quot; bob & quot; och app.req.input [& quot; lösenord & quot;] == & quot; abrakadabra & quot;:
- app.session.kill ()
- app.session [& quot; auktoriserat & quot;] = Sann
- annars:
- # ...
- WebSockets: Realtime meddelandehantering. (Kräver gevent, greenlet, gevent-WebSocket)
- Du hittar dessa källkoden i src / prover / websocketchat katalogen.
- @ app.get (& quot; chat & quot;)
- def chat ():
- ws = app.req.websocket
- SOCKETS.add (ws)
- app.logger.info (& quot; accepterar:% s & quot;% repr (ws.socket))
- medan sant:
- msg = ws.receive ()
- Om msg är Ingen:
- break
- error_sockets = set ([])
- för si INGÅNG:
- prova:
- s.send (msg)
- utom Exception, e:
- error_sockets.add (er)
- för si error_sockets:
- SOCKETS.remove (er)
- Python
& Nbsp; append = tpl.append
& Nbsp; max_page = int (Math.ceil (räkna / float (n)))
& Nbsp; om sidan> max_page: page = 1
& Nbsp; start, slut = max (sida-4, 1), min (sidan + 4, max_page)
& Nbsp; append ("
& Nbsp; ((sida-1) <1 och ("föregående-off", "& laquo; Föregående") eller
& Nbsp; ("tidigare", " & laquo; Föregående "% (helper.page_link (c, sida-1)))))
& Nbsp; om start = 1: append ("
& Nbsp; om start> 2: append ("
& Nbsp; for i in Irange (start, slut + 1):
& Nbsp; om jag == sida:
& Nbsp; append ("
& Nbsp; annars:
& Nbsp; append ("
& Nbsp; om slutet <(max_page-1): append ("
& Nbsp; om slutet = max_page: append ("
& Nbsp; append ("
& Nbsp; ((sida + 1)> max_page och ("next-off", "Next & raquo;") eller
& Nbsp; ("nästa", " Nästa & raquo; "% (helper.page_link (c, sida + 1)))))
& Nbsp; append ("")
& Nbsp; return "" .join (tpl)
#}}}
# Db {{{
def find_entry_by_id (entry_id):
& Nbsp; retur app.db.select_one ([Entry], dir = "? Id =", värden = [entry_id])
def find_entries (offset, gräns):
& Nbsp; retur app.db.select ([Entry],
& Nbsp; dir = "? 1 ordning genom created_at desc limit offset?",
& Nbsp; värden = [gräns, offset])
def count_entries ():
& Nbsp; retur app.db.select_one ([Entry], välj = "SELECT count (id) som räknas från% (tabeller) s") räknas.
#}}}
med app.filter (context_setup_filter):
& Nbsp; @ app.get ("")
& Nbsp; def index ():
& Nbsp; limit = app.vars.entry_per_page
& Nbsp; offset = gräns * (int (app.req.input.get ("sida", 1)) - 1)
& Nbsp; c.entries = find_entries (offset, gräns)
& Nbsp; c.count = count_entries ()
& Nbsp; retur app.renderer.show_entries ({"c": c})
& Nbsp; @ app.get ("artiklar / (int: d +)")
& Nbsp; def show_entry (entry_id):
& Nbsp; c.entry = find_entry_by_id (entry_id)
& Nbsp; c.title + = "::% s"% c.entry.title
& Nbsp; retur app.renderer.show_entry ({"c": c})
& Nbsp; @ app.get ("admin / signin")
& Nbsp; def admin_signin_form ():
& Nbsp; retur app.renderer.admin_signin_form ({"c": c})
& Nbsp; @ app.post ("admin / signin")
& Nbsp; def admin_signin ():
& Nbsp; om app.req.input ["namn"] == app.vars.admin_name och
& Nbsp; app.req.input ["lösenord"] == app.vars.admin_password:
& Nbsp; app.session ["signin"] = Sann
& Nbsp; app.res.redirect (app.url.admin_index ())
& Nbsp; annars:
& Nbsp; c.errors = ["signin misslyckades."]
& Nbsp; retur app.renderer.admin_signin_form ({"c": c})
& Nbsp; med app.filter (admin_filter, flash_filter):
& Nbsp; @ app.get ("admin")
& Nbsp; def admin_index ():
& Nbsp; retur app.renderer.admin_index ({"c": c})
& Nbsp; @ app.get ("admin / signout")
& Nbsp; def admin_signout ():
& Nbsp; app.session.kill ()
& Nbsp; app.res.redirect (app.url.admin_signin_form ())
& Nbsp; @ app.get ("admin / post / ny")
& Nbsp; def admin_entry_new ():
& Nbsp; om inte hasattr (c, "post"):
& Nbsp; c.entry = Entry (title = "", kropp = "")
& Nbsp; återvända app.renderer.admin_entry_new ({"c": c})
& Nbsp; @ app.post ("admin / post / skapa")
& Nbsp; def admin_entry_create ():
& Nbsp; c.entry = Entry (** app.req.input ["post"])
& Nbsp; c.errors = c.entry.validate ()
& Nbsp; om c.errors:
& Nbsp; returnera admin_entry_new (c)
& Nbsp; app.db.insert (c.entry)
& Nbsp; app.session ["flash"] ["meddelande"] = "Entry till."
& Nbsp; app.res.redirect (app.url.admin_index ())
om inte os.path.exists (DB_FILE):
& Nbsp; db = app.ext.database.create_new_session ()
& Nbsp; db.autocommit = Sant
& Nbsp; prova:
& Nbsp; db.execute ("" "CREATE TABLE poster (
& Nbsp; id INTEGER PRIMARY KEY NOT NULL,
& Nbsp; title TEXT,
& Nbsp; brödtext,
& Nbsp; created_at TIMESTAMP); "" ")
& Nbsp; db.execute (DatabaseSessionStore.SCHEMA)
& Nbsp; db.execute (DatabaseSessionStore.INDEX)
& Nbsp; äntligen:
& Nbsp; db.close ()
Om __name__ == "__main__":
& Nbsp; app.serve_forever ()
& Nbsp;
File Type
Funktioner :
Krav :
Kommentarer hittades inte