Python-Adventskalender 2012 (Web Framework) Ich bin verantwortlich für den 5. Tag von #python_adv. Dieser Artikel wird ein Multi-Post mit meinem Blog sein. http://methane.hatenablog.jp/entry/2012/12/05/134206
IDEs wie PyCharm haben begonnen, Flask zu unterstützen, und Flask wird nach Django das zweitgrößte Webframework für Python. (Obwohl die Python3-Unterstützung dafür langsam ist)
Apropos Flasche, es ist berühmt für die Person, die das Mikro-Framework Hello World leicht schreiben kann.
hello.py
import flask
app = flask.Flask(__name__)
@app.route('/')
def index():
return "Hello, World."
app.run(debug=True)
Wenn man das betrachtet, sieht es aus wie ein Spielzeug, aber Flask hat eine solide Grundlage, auf der Sie mehrere Apps auf einem Python-Interpreter oder mehreren Instanzen einer App platzieren können, und es ist ein Modul, das Blueprint verwendet. Es hat auch ein Framework, das für große Anwendungen verwendet werden kann.
Im Vergleich zum Vollstapeltyp-Framework ist der Punkt, an dem Bibliotheken wie OR-Mapper, Formularbibliothek und AJAX-Unterstützungsbibliothek nicht integriert sind, mikro. Wenn Sie jedoch eine solche Bibliothek selbst auswählen möchten, ändern Sie das Vollstapeltyp-Framework. Ich denke, es ist oft einfacher, Flask zu erweitern, als es zu tun.
Heute gebe ich Ihnen einen kurzen Überblick darüber, wie Sie Flask für jede App anpassen können. (Es ist Zeit, eine modulare Flask-Erweiterung wie Flask-SQLAlchemy zu erstellen.)
Es gibt zwei Möglichkeiten, die Flask-Klasse zu erben und anzupassen sowie die Methoden der Flask-Instanz zu verwenden. In den meisten Fällen reicht jedoch letztere aus.
Es gibt viele Anpassungsfunktionen, aber es gibt nicht viele Muster, wie sie erweitert werden können. Deshalb zeige ich Ihnen drei Muster.
Wenn Sie beispielsweise die im Headerteil standardmäßig verwendeten Variablen für die gesamte Anwendung vorbereiten, ist dies praktisch, da Sie die Variablen nicht jedes Mal in render_response festlegen müssen. Flask bietet eine Erweiterungsmethode, die "create_jinja_environment" überschreibt. Es ist jedoch einfacher, sie direkt auf dieser Ebene hinzuzufügen.
import random
app.jinja_env.globals['random'] = random.randint
Beachten Sie jedoch, dass jinja_env beim ersten Zugriff mit create_jinja_environment erstellt wird, sodass das Timing beschleunigt wird. In den meisten Fällen sollte dies in Ordnung sein. Verwenden Sie jedoch bei Bedarf die unten beschriebene Erweiterungsmethode im Dekorationsstil.
@app.before_first_request
def extend_jinja_env():
app.jinja_env.globals['random'] = random.randint
Es ist eine gute Idee, zu verzögern, bis die erste Anforderung eintrifft, oder create_jinja_environment normal zu überschreiben.
Da es für jede Anwendung nur eine Jinja-Umgebung gibt, ist es nicht möglich, Variablen für jede Blaupause hinzuzufügen. Schreiben Sie in diesem Fall die Renderfunktion in das Modul, das die Blaupause erstellt.
def render(tmpl, **kw):
kw['rnd'] = random.randrange(1000)
return flask.render_response(tmpl, **kw)
Ein Beispiel für die Verwendung der Methode zum direkten Ändern der Attribute der App besteht darin, session_interface zu ersetzen und Ihren eigenen Session-Handler zu verwenden.
PS: Ich konnte Variablen mit den Kontext-Prozessor-Dekoratoren von Flask und Blueprint hinzufügen. Es ist auch für jede Blaupause möglich. Dies ist eine gute Möglichkeit, unterschiedliche Werte für jede Anforderung zu speichern.
http://flask.pocoo.org/docs/templating/#context-processors
Wenn Sie die Datums- und Uhrzeitangabe mit +0 Zeitzone als Japanzeit in der Vorlage anzeigen möchten, z. B. wenn die Uhrzeit in UTC in der Datenbank gespeichert ist, obwohl es sich um eine Anwendung für Japan handelt, können Sie einen Filter wie diesen hinzufügen.
@app.template_filter()
def jptime(dt, format='%Y-%m-%d %H:%M:%S'):
u"""Konvertieren Sie die utc-Zeit in eine Zeichenfolge in dem von der japanischen Zeit angegebenen Format."""
local = dt + datetime.timedelta(hours=9)
return local.strftime(format)
Es sieht so aus, wenn man es benutzt.
Zuletzt geändert: {{ post.last_modified | jptime('%m/%d %H:%M') }}
@ app.template_filter ist nicht nur ein Dekorator, sondern ein Dekorator im Funktionsstil. Sie können jedoch in dieses Argument name =" JT "
schreiben, um den Funktionsnamen vom Filternamen in der Vorlage zu trennen. ..
Es gibt viele andere Erweiterungen, die Dekoratoren verwenden. Die meisten davon sind auch in Blueprint verfügbar. Beispielsweise erfordert ein Blueprint eine Authentifizierung für alle Anforderungen.
from myapp.auth import auth
bp = flask.Blueprint('admin', __name__)
@bp.route('/')
@auth.required
def index():
#…
@bp.route('/profile')
@auth.required
def profile():
#…
Wenn Sie eine Funktion bei before_request registrieren, wird sie vor dem Aufruf der Ansichtsfunktion aufgerufen.
Außerdem wird der Aufruf der Ansichtsfunktion übersprungen, wenn diese Funktion eine Antwort zurückgibt, sodass Sie den Dekorator @ auth.required
für die Ansichtsfunktion verwenden können.
bp = flask.Blueprint('admin', __name__)
@bp.before_request
@auth.required
def before_request():
flask.g.user = auth.get_user()
#…
Es gibt zwei Arten von Flask-Erweiterungsdekoratoren, einer ist ein Funktionstyp und der andere ist nur ein Dekorator, aber keine Sorge, Sie können die Ausnahme in einer Aufnahme sehen, indem Sie sich die Stapelspur ansehen, auch wenn Sie sie falsch verwenden.
Informationen über die aktuell ausgeführte Anwendung und Informationen über die aktuell verarbeitete Anforderung, z. B. flask.current_app und flask.request, werden mithilfe von threadlokalen Stapeln verwaltet, die als Kontextstapel bezeichnet werden. Mit dem Stapel können Sie andere Flask-Apps in der Flask-App ausführen. Wenn Sie eine App erweitern möchten, bearbeiten Sie den Kontext oben im Stapel.
Angenommen, Sie möchten für jede Anforderung eine Verbindung zur Datenbank herstellen und am Ende die Verbindung trennen.
In diesem Fall ist der Anforderungskontext in Ordnung, aber der App-Kontext, der auch von einem Skript ohne HTTP-Anforderung aus problemlos verwendet werden kann, ist besser geeignet.
def _connect_db():
return MySQLdb(**app.config['MYSQL_OPTS'])
def get_db():
top = flask._app_context_stack.top
if top is None:
raise RuntimeError('working outside of application context')
if not hasattr(top, 'db'):
top.db = _connect_db()
return top.db
@app.teardown_appcontext
def _close_db():
top = flask._app_context_stack.top
if top is None:
raise RuntimeError('working outside of application context')
if hasattr(top, 'db'):
top.db.close()
top.db = None
Wenn Sie es nur zu einer globalen Variablen db machen möchten, anstatt jedes Mal get_db () aufzurufen, verwenden Sie LocalProxy.
from werkzeug.local import LocalProxy
db = LocalProxy(get_db)
LocalProxy hat jedoch einen gewissen Overhead, sodass Sie es möglicherweise nicht verwenden möchten, wenn Sie in einer Anforderung häufig hunderte Male auf Attribute zugreifen.
In der Praxis ist es einfacher, die Variable flask.g im Anforderungskontext zu verwenden, ohne den Kontext direkt ändern zu müssen. (Beispiel: http://flask.pocoo.org/docs/patterns/sqlite3/)
Ich denke, es reicht aus, sich nur dann direkt mit dem Kontext zu befassen, wenn Sie ihn unabhängig von Ihrer eigenen Anwendung wiederverwenden möchten, z. B. beim Erstellen einer Flask-Erweiterung.
Die Flask-Sitzung kann durch Ersetzen von Flask.session_interface angepasst werden.
Diese Anpassung ist recht einfach. Da sie jedoch vor before_request aufgerufen wird, müssen Sie vor der Authentifizierung oder Blueprint ein Sitzungsobjekt generieren, wenn Sie beispielsweise eine Sitzungs-ID generieren möchten, die einer Benutzer-ID in einer Anwendung zugeordnet ist, für die eine Anmeldung erforderlich ist Es ist problematisch, wenn Sie die Behandlung von Sitzungen im Detail steuern möchten. Hier erfahren Sie, wie Sie flask.session deaktivieren.
app.session_interface = flask.sessions.NullSessionInterface()
Wenn Sie danach Ihre eigene Sitzung in flask.g.session usw. ablegen und das Verhalten mit before_request, teardown_request usw. definieren, können Sie die Sitzung freier steuern. Informationen zur Verwendung von Becher mit Flasche finden Sie beispielsweise unter http://flask.pocoo.org/snippets/61/ und passen Sie sie nach Bedarf an.
Recommended Posts