# 抛出错误页面 from flask import abort @app.route('/user/<id>') def get_user(id): user = load_user(id) if not user: abort(404) return '<h1>Hello, {}</h1>'.format(user.name)
# url_for() url_for('.index') """ In its simplest usage, this function takes the view function name (or endpoint name for routes defined with app.add_url_route()) as its single argument and returns its URL. For example, in the current version of hello.py the call url_for('index') would return /, the root URL of the application. Calling url_for('index', _external=True) would instead return an absolute URL, which in this example is http://localhost:5000/. """
(venv) $ export FLASK_APP=hello.py (venv) $ flask run * Serving Flask app "hello" * * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
(venv) $ set FLASK_APP=hello.py (venv) $ flask run * Serving Flask app "hello" * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) # debug模式 (venv) $ export FLASK_APP=hello.py (venv) $ export FLASK_DEBUG=1 (venv) $ flask run * Serving Flask app "hello" * Forcing debug mode on * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit) * Restarting with stat * Debugger is active! * Debugger PIN: 273-181-528 # 命令行参数 (venv) $ flask run --host 0.0.0.0 * Serving Flask app "hello" * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)
The Request-Response Cycle 请求 响应上下文
from flask import request @app.route('/') defindex(): user_agent = request.headers.get('User-Agent') return'<p>Your browser is {}</p>'.format(user_agent)
post
from flask import request
@app.route('/login', methods=['POST', 'GET']) deflogin(): error = None if request.method == 'POST': if valid_login(request.form['username'], request.form['password']): return log_the_user_in(request.form['username']) else: error = 'Invalid username/password' # the code below is executed if the request method # was GET or the credentials were invalid return render_template('login.html', error=error)
classStudent(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String) classes = db.relationship('Class', secondary=registrations, backref=db.backref('students', lazy='dynamic'), lazy='dynamic')
classClass(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String)
操作
>>> s.classes.append(c) >>> db.session.add(s)
>>> s.classes.all() >>> c.students.all()
>>> s.classes.remove(c)
example
view
@app.route('/', methods=['GET', 'POST']) defindex(): form = NameForm() if form.validate_on_submit(): user = User.query.filter_by(username=form.name.data).first() if user isNone: user = User(username=form.name.data) db.session.add(user) db.session.commit() session['known'] = False else: session['known'] = True session['name'] = form.name.data form.name.data = '' return redirect(url_for('index')) return render_template('index.html', form=form, name=session.get('name'), known=session.get('known', False))
html
{% extends "base.html" %}{% import "bootstrap/wtf.html" as wtf %} {% block title %}Flasky{% endblock %} {% block page_content %} <divclass="page-header"> <h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}!</h1> {% if not known %} <p>Pleased to meet you!</p> {% else %} <p>Happy to see you again!</p> {% endif %} </div> {{ wtf.quick_form(form) }} {% endblock %}
# 加上注释便于回滚 (venv) $ flask db migrate -m "initial migration" INFO [alembic.migration] Context impl SQLiteImpl. Generating /home/flask/flasky/migrations/versions/1bc 594146bb5_initial_migration.py...done
(venv) $ flask db upgrade INFO [alembic.migration] Context impl SQLiteImpl. INFO [alembic.migration] Will assume non-transactional DDL. INFO [alembic.migration] Running upgrade None -> 1bc594146bb5, initial migration
(venv) $ export MAIL_USERNAME=<Gmail username> (venv) $ export MAIL_PASSWORD=<Gmail password> # windows (venv) $ set MAIL_USERNAME=<Gmail username> (venv) $ set MAIL_PASSWORD=<Gmail password>
shell 命令行中发送邮件
(venv) $ flask shell >>> from flask_mail import Message >>> from hello import mail >>> msg = Message('test email', sender='you@example.com', ... recipients=['you@example.com']) >>> msg.body = 'This is the plain text body' >>> msg.html = 'This is the <b>HTML</b> body' >>> with app.app_context(): ... mail.send(msg) ...
from flask import Flask from flask_bootstrap import Bootstrap from flask_mail import Mail from flask_moment import Moment from flask_sqlalchemy import SQLAlchemy from config import config
bootstrap = Bootstrap() mail = Mail() moment = Moment() db = SQLAlchemy()
app/main/views.py: Blueprint with application routes
from flask import render_template, session, redirect, url_for, current_app from .. import db from ..models import User from ..email import send_email from . import main from .forms import NameForm
@main.route('/', methods=['GET', 'POST']) defindex(): form = NameForm() if form.validate_on_submit(): user = User.query.filter_by(username=form.name.data).first() if user isNone: user = User(username=form.name.data) db.session.add(user) session['known'] = False if current_app.config['FLASKY_ADMIN']: send_email(current_app.config['FLASKY_ADMIN'], 'New User', 'mail/new_user', user=user) else: session['known'] = True session['name'] = form.name.data return redirect(url_for('.index')) return render_template('index.html', form=form, name=session.get('name'), known=session.get('known', False))
Application Script
flasky.py: Main script
import os from flask_migrate import Migrate from app import create_app, db from app.models import User, Role
@app.cli.command() deftest(): """Run the unit tests.""" import unittest tests = unittest.TestLoader().discover('tests') unittest.TextTestRunner(verbosity=2).run(tests)
运行单元测试
(venv) $ flask test test_app_exists (test_basics.BasicsTestCase) ... ok test_app_is_testing (test_basics.BasicsTestCase) ... ok .---------------------------------------------------------------------- Ran 2 tests in 0.001s
OK
修改模型
(venv) $ flask db upgrade INFO [alembic.runtime.migration] Context impl SQLiteImpl. INFO [alembic.runtime.migration] Will assume non-transactional DDL. INFO [alembic.runtime.migration] Running upgrade -> 38c4e85512a9, initial migration
from flask import Flask, render_template, session, redirect, url_for, flash @app.route('/', methods=['GET', 'POST']) defindex(): form = NameForm() if form.validate_on_submit(): old_name = session.get('name') if old_name isnotNoneand old_name != form.name.data: flash('Looks like you have changed your name!') session['name'] = form.name.data return redirect(url_for('index')) return render_template('index.html', form = form, name = session.get('name'))