promienie jest WSGI kompatybilny ramy internetowa zaprojektowana dla małych aplikacji internetowych. Obsługuje zarówno Python 2.7 i Python 3.2. Promienie obsługuje wielobajtowe-charcters prawidłowo (Ważne jest dla mnie, więc jestem japoński).
instalacji
easy_install promienie
lub
pip install -e git: //github.com/yuin/rays.git#egg=rays
lub pobrać plik zip z https://github.com/yuin/rays/zipball/master i
python setup.py install
Przykład
Możesz znaleźć te kod źródłowy w próbkach / katalogu src / blog.
index.py:
od promieni import *
z rays.compat import *
import sys, os.path, matematyka, contextlib
z datetime import datetime
Import gwintowania
app = Application ()
Przenieść ją do app_dir = os.path.dirname (__ FILE__)
DB_FILE = os.path.join (przenieść ją do app_dir "test.db")
c = threading.local ()
app.config ([
& Nbsp; ("debug", prawda),
& Nbsp; ("renderer", {"template_dir": os.path.join (przenieść ją do app_dir, "szablony"),
& Nbsp; "cache_dir": os.path.join (przenieść ją do app_dir, "templates / cache")}),
& Nbsp; ("DatabaseExtension", {"Połączenie": DB_FILE, "transakcja": "commit_on_success"}),
& Nbsp; ("SessionExtension", {"magazyn": "bazy danych", "tajne": "asdfeE305Gs0lg",
& Nbsp; "cookie_path": "admin"}),
& Nbsp; ("StaticFileExtension", {"url": "statyka /", "Droga": os.path.join (przenieść ją do app_dir, "Statyka")}),
& Nbsp; ("nazwa_administratora", "admin"),
& Nbsp; ("hasło_administratora", "hasło"),
& Nbsp; ("blog_title", "Mój blog"),
& Nbsp; ("entry_per_page", 3),
])
Klasa BaseModel (model): # {{{
& Nbsp; def class_init (CLS):
& Nbsp; Model.class_init (CLS)
& Nbsp; @ cls.hook ("before_create")
& Nbsp; def before_create (self):
& Nbsp; self.created_at = DateTime.Now ()
#}}}
Klasa wprowadzająca (BaseModel): # {{{
& Nbsp; TABLE_NAME = "wpisy"
& Nbsp; def potwierdzić (self):
& Nbsp; wynik = []
& Nbsp; jeśli nie self.title: result.append (". Wymagane Tytuł")
& Nbsp; len (self.title)> 100: result.append ("Tytuł zbyt długo.")
& Nbsp; len (self.title) <2: result.append (". Tytuł jest za krótka")
& Nbsp; jeśli nie self.body: result.append (". Wymagane Body")
& Nbsp; return result
#}}}
# filtry {{{
context_setup_filter def (*, ** k):
& Nbsp; c.title = app.vars.blog_title
& nbsp; c.errors = []
& Nbsp; wydajność
admin_filter def (*, ** k):
& Nbsp; jeśli nie app.session ["logować"]:
& Nbsp; app.res.redirect (app.url.admin_signin ())
& Nbsp; wydajność
flash_filter def (*, ** k):
& Nbsp; dyr = app.session ["logować"]
& Nbsp; dyr:
& Nbsp; app.session ["błysku"] = app.session ["błysku"] lub {}
& Nbsp; klucze = list (iter_keys (app.session ["błysku"]))
& Nbsp; wydajność
& Nbsp; dyr:
& Nbsp; na klucz w klawisze: del app.session ["Flash"] [key]
#}}}
# pomocnicy {{{
@ App.helper
@ Contextlib.contextmanager
main_block def (pomocnik):
& Nbsp; helper.concat ("
& Nbsp; z helper.capture ("__ main_block"):
& Nbsp; wydajność
& Nbsp; helper.concat (helper.captured ("__ main_block"))
& Nbsp; helper.concat ("
@ App.helper
show_errors def (pomocnicze, błędy):
& Nbsp; błędy:
& Nbsp; helper.concat ("
- ")
- " + błąd + " ")
& Nbsp; do błędu błędów:
& Nbsp; helper.concat ("
& Nbsp; helper.concat ("
@ App.helper
show_message def (pomocnik, komunikat):
& Nbsp; wiadomości:
& Nbsp; helper.concat ("
& Nbsp; helper.concat (komunikat)
& Nbsp; helper.concat ("
@ App.helper
def format_datetime (pomocnik, dt):
& Nbsp; powrócić dt.strftime ("..% M% d% r /% I% p% Z") niższa ().
@ App.helper
def hatom_published (pomocnik, wpis):
& Nbsp; return "" "% s " ""% (entry.created_at.isoformat (), helper.format_datetime (entry.created_at))
@ App.helper
format_body def (pomocnik, ciała):
& Nbsp; body.replace powrotu (" n", "
")
@ App.helper
page_link def (pomocnik, strona):
& Nbsp; "? Strona =% d" app.url.index powrotu () +% strona
@ App.helper
paginacja def (pomocnik, hrabia, strona):
& Nbsp; page = int (strona)
& 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 "%
- Marszruty:. Prosty, ale potężny,
- Trasy są definiowane przez wyrażeń regularnych i typu konstruktorów:
- @ app.get (& quot; członek / (int: d +) & quot;)
- show_member def (member_id):
- # ...
- app.url ma łatwe odniesienie do tras:
- app.url.show_member (1) # = & gt; & Quot; http: // somehost / członek / 1 & quot;
- Filtry i haki. Pisanie kodu DRY
- Haki zostanie ponownie na następujące punkty hak.
- before_initialize
- after_initialize
- before_call
- before_dispatch
- before_action
- before_start_response
- Haki przykład:
- @ app.hook (& quot; before_start_response & quot;)
- def status_log_hook (*):
- jeśli app.res.is_success:
- app.logger.info (& quot; sukces & quot;)
- Elif app.res.is_abort:
- app.logger.warn (& quot; anulować & quot;)
- innego:
- app.logger.error (& quot; błąd:% s & quot;% Unicode (app.res.exception))
- Filtry umożliwiają działania w celu uruchomienia kodu przed i po obróbce:
- def filtrować (* args):
- # wstępnego przetwarzania
- Wydajność
- # post-processing,
- z app.filter (filtr):
- @ app.get (& quot; członek / (int: d +) & quot;)
- show_member def (member_id):
- # ...
- Szablony. Szybkie i elastyczne,
- Aby uczynić index.html, app.renderer.index (vars).
- Struny otoczone & quot; & quot; będą interpretowane jako kod Pythona.
- & lt; % = 10% & gt;
- & lt; % = Python kod% & gt; zostanie zastąpiony przez wyniku realizacji & quot; kodzie Pythona & quot;.
- Zawsze applys filtra (tj. Cgi.escape). Aby ją wyłączyć, należy użyć
- Wiele sposób wyrazić bloków:
- & lt; % - Dla i w xrange (10): -% & gt;
- & lt; % =% & Gt;
- & lt; %% & Gt;
- & lt; % - Dla i w xrange (10) {: -% & gt;
- & lt; % =% & Gt;
- & lt; %:}% & Gt;
- & lt; % - Dla i w xrange (10): -% & gt;
- & lt; % =% & Gt;
- & lt; % End% & gt;
- Zintegrowane bbli pomocnicy przydatne szablonu:
- & lt; % Z h.capture (& quot; body & quot;):% & gt;
- foo
- & lt; %% & Gt;
- & lt; % = Ciało% & gt;
- ORMS bbli: Prosta nakładka na wbudowany moduł sqlite3:.
- Wynik = app.db.select ([serwisu, strona], dyr = & quot;? Page.site_id = Site.id i Page.id = & quot ;, wartości = [1]),
- wydruk (wynik [0] .site)
- wydruk (wynik [0] .strona)
- app.db.insert (strona),
- app.db.update (strona),
- app.db.delete (strona),
- app.db.shell () # interaktywne sqlite3 powłoki
- Sesje bbli:
- @ app.get (& quot; logować & quot;)
- def logować ():
- jeśli app.req.input [& quot; nazwa & quot;] == & quot; bob & quot; i app.req.input [& quot; hasła & quot;] == & quot; abrakadabra & quot;
- app.session.kill ()
- app.session [& quot; upoważnione & quot;] = true
- innego:
- # ...
- WebSockets: Realtime wiadomości. (Wymaga gevent, greenlet, gevent-WebSocket)
- Można znaleźć te kody źródłowe w src / próbek / websocketchat katalogu.
- @ app.get (& quot; porozmawiać & quot;)
- def czat ():
- ws = app.req.websocket
- SOCKETS.add (ws),
- app.logger.info (& quot; przyjmuje:% s & quot;% repr (ws.socket))
- while True:
- msg = ws.receive ()
- jeśli msg jest brak:
- przerwa
- error_sockets = set ([])
- dla s w gniazdach:
- spróbować:
- s.send (MSG),
- chyba wyjątek, e:
- error_sockets.add (s)
- dla sw error_sockets:
- SOCKETS.remove (s)
- Python
& Nbsp; dołączyć = tpl.append
& Nbsp; max_page = int (Math.ceil (liczba / float (n)))
& Nbsp; jeśli strona> max_page: strona = 1
& Nbsp; początek, koniec = max (strona-4, 1), min (strona + 4, max_page)
& Nbsp; dołączania ("
& Nbsp; ((strona 1) <1 a ("poprzednie-off", "& laquo; Poprzednia") lub
& Nbsp; ("poprzedni", " prev & laquo; Poprzednia >"% (helper.page_link (c, strona-1)))))
& Nbsp; start = 1: append ("
& Nbsp; Start> 2: append ("
& Nbsp; i w irange (początek, koniec + 1):
& Nbsp; gdybym == strona:
& Nbsp; dołączania ("
& Nbsp; indziej:
& Nbsp; dołączania ("
& Nbsp; end <(max_page-1): append ("
& Nbsp; end = max_page: append ("
& Nbsp; dołączania ("
& Nbsp; ((strona + 1)> max_page i ("next-off", "Next & raquo;") lub
& Nbsp; ("następny", " następnego Next & raquo; >"% (helper.page_link (c, strona + 1)))))
& Nbsp; dołączania ("")
& Nbsp; return "" .join (TPL)
#}}}
# Db {{{
find_entry_by_id def (entry_id):
& Nbsp; app.db.select_one powrotu ([Wstęp], dyr = "? Id =" Wartości = [entry_id])
find_entries def (offset, limitu):
& Nbsp; return app.db.select ([Wstęp],
& Nbsp; dyr = "? 1 order by limitu created_at malejąco offset?",
& Nbsp; wartości = [limitu, offset])
count_entries def ():
& Nbsp; app.db.select_one powrotu ([Wstęp], wybierz = "SELECT count (id), jak liczyć od% (tabel) s") liczy.
#}}}
z app.filter (context_setup_filter):
& Nbsp; @ app.get ("")
& Nbsp; def index ():
& Nbsp; limit = app.vars.entry_per_page
& Nbsp; offset = krańcowy * (int (app.req.input.get ("strona", 1)) - 1)
& Nbsp; c.entries = find_entries (offset, limitu)
& Nbsp; c.count = count_entries ()
& Nbsp; app.renderer.show_entries powrotne ({"c": c})
& Nbsp; @ app.get ("Artykuły / (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; return app.renderer.show_entry ({"c": c})
& Nbsp; @ app.get ("admin / logować")
& Nbsp; def admin_signin_form ():
& Nbsp; return app.renderer.admin_signin_form ({"c": c})
& Nbsp; @ app.post ("admin / logować")
& Nbsp; def admin_signin ():
& Nbsp; app.req.input ["name"] == app.vars.admin_name i
& Nbsp; app.req.input ["hasło"] == app.vars.admin_password:
& Nbsp; app.session ["logować"] = true
& Nbsp; app.res.redirect (app.url.admin_index ())
& Nbsp; indziej:
& Nbsp; c.errors = ["logować nie powiodło się."]
& Nbsp; return app.renderer.admin_signin_form ({"c": c})
& Nbsp; z app.filter (admin_filter, flash_filter):
& Nbsp; @ app.get ("admin")
& Nbsp; def admin_index ():
& Nbsp; return app.renderer.admin_index ({"c": c})
& Nbsp; @ app.get ("admin / rezygnacja ze subskrypcji")
& Nbsp; def admin_signout ():
& Nbsp; app.session.kill ()
& Nbsp; app.res.redirect (app.url.admin_signin_form ())
& Nbsp; @ app.get ("admin / entry / nowych")
& Nbsp; def admin_entry_new ():
& Nbsp; jeśli nie hasattr (c, "wejście"):
& Nbsp; c.entry = Wejście (title = "", ciało = "")
& Nbsp; powrócić app.renderer.admin_entry_new ({"c": c})
& Nbsp; @ app.post ("admin / entry / stworzyć")
& Nbsp; def admin_entry_create ():
& Nbsp; c.entry = Wejście (** app.req.input ["Wpis"])
& Nbsp; c.errors = c.entry.validate ()
& Nbsp; c.errors:
& Nbsp; powrócić admin_entry_new (c)
& Nbsp; app.db.insert (c.entry)
& Nbsp; app.session ["błysku"] ["wiadomość"] = "Pozycja dodana."
& Nbsp; app.res.redirect (app.url.admin_index ())
jeśli nie os.path.exists (DB_FILE):
& Nbsp; db = app.ext.database.create_new_session ()
& Nbsp; db.autocommit = True
& Nbsp; spróbuj:
& Nbsp; db.execute ("" "CREATE pozycji w tabeli (
& Nbsp; id INTEGER PRIMARY KEY NOT NULL,
& Nbsp; tytuł TEKST,
& Nbsp; TEKST ciała,
& Nbsp; created_at TIMESTAMP); "" "),
& Nbsp; db.execute (DatabaseSessionStore.SCHEMA)
& Nbsp; db.execute (DatabaseSessionStore.INDEX)
& Nbsp; na końcu:
& Nbsp; db.close ()
jeśli __name__ == "__main__":
& Nbsp; app.serve_forever ()
& Nbsp;
File Type
Opis :
Wymagania :
Komentarze nie znaleziono