介绍
有许多方法和约定用于构造Python Web应用程序。虽然某些框架随附了用于自动化和简化任务(和头痛)的工具(用于脚手架),但几乎所有解决方案都依赖于打包/模块化应用程序,因为代码库在逻辑上跨相关文件和文件夹分布。 极简的Web应用程序开发框架Large Flask,有自己的- 蓝图 。 在这篇DigitalOcean文章中,我们将看到如何创建应用程序目录,并将其结构化为使用Flask的蓝图创建的可重用组件。这些部件极大地允许(并简化)应用程序组件的维护和开发。词汇表
1. Flask:最低限度的应用程序开发框架
2.我们在这篇文章中的选择
3.准备Flask系统
- 准备操作系统
- 设置Python,pip和virtualenv
4.结构化应用程序目录
- 创建应用程序文件夹
- 创建虚拟环境
- 创建应用程序文件
- 安装Flask
5.使用模块和蓝图(组件)
- 模块基础
- 模块模板
6.创建应用程序(run.py, 初始化的.py等)
- 使用nano编辑run.py
- 使用nano编辑config.py
7.创建模块/组件
- 第1步:构造模块
- 第2步:定义模块数据模型
- 第3步:定义模块表单
- 第4步:定义应用程序控制器(视图)
- 第5步:设置在“应用程序/ 初始化的.py”的应用
- 第6步:创建模板
- 第7步:查看您的模块在行动
Flask:最低限度的应用程序开发框架
Flask是一个简约(或微)框架,避免强加处理关键事物的方式。相反,Flask允许开发人员使用他们所需要的和熟悉的工具。为此,它有自己的扩展索引和已经存在的大量工具,以处理从登录到日志的几乎所有内容。 它不是一个严格的“常规”框架,并且部分依赖于配置文件,坦率地说,使许多事情更容易,当谈到开始和保持的东西。我们在这篇文章中的选择
正如我们刚刚在上一节中讨论的那样,Flask的做事方式涉及使用最舒适的工具。在我们的文章中,我们将使用 - 或许 - 在扩展和库(即数据库提取层)方面最常见(和明智)的选择。这些选择包括:- SQLAlchemy(通过Flask-SQLAlchemy)
- WTForms(通过Flask-WTF)
Flask-SQLAlchemy
向Flask添加SQLAlchemy支持。快速和容易。 这是已批准的扩展程序。Author: Armin Ronacher
PyPI Page: Flask-SQLAlchemy
Documentation: Read docs @ packages.python.org
On Github: [mitsuhiko/flask-sqlalchemy](https://github.com/mitsuhiko/flask-sqlalchemy)
Flask-WTF
Flask-WTF提供与WTForms的简单集成。此集成包括可选的CSRF处理以提高安全性。 这是已批准的扩展程序。Author: Anthony Ford (created by Dan Jacob)
PyPI Page: Flask-WTF
Documentation: Read docs @ packages.python.org
On Github: [ajford/flask-wtf](https://github.com/mitsuhiko/flask-wtf)
准备Flask系统
在我们开始构建大型Flask应用程序之前,让我们准备我们的系统并下载(和安装)Flask分发。 注意:我们将在运行最新版本可用的操作系统(如Ubuntu的13)刚实例化的Droplet合作。强烈建议您在新系统上测试一切 - 尤其是如果您积极为客户服务。准备操作系统
为了有一个稳定的服务器,我们必须有所有相关的工具和库,最新的和良好的维护。 为了确保我们有最新的可用版本的默认应用程序,让我们从更新开始。 对于基于Debian的系统(即Ubuntu,Debian)运行以下命令:aptitude update
aptitude -y upgrade
要获得必要的开发工具,请使用以下命令安装“build-essential”:
aptitude install -y build-essential python-dev python2.7-dev
设置Python,pip和virtualenv
在Ubuntu和Debian,最新版本的Python解释器 - 你可以使用 - 默认情况下。它使我们只有有限数量的额外的软件包安装:- python-dev的 (开发工具)
- PIP(管理包)
- 的virtualenv(创建隔离,虚拟
pip
pip是一个包管理器,它将帮助我们安装我们需要的应用程序包。 运行以下命令安装pip:curl https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py | python -
curl https://raw.github.com/pypa/pip/master/contrib/get-pip.py | python -
export PATH="/usr/local/bin:$PATH"
virtualenv
最好是一起包含它自己的 环境中的Python应用程序与所有的依赖。环境可以被最好地描述(简单地)作为一切都驻留的孤立位置(目录)。为此,使用称为virtualenv的工具。 运行以下命令以使用pip安装virtualenv:sudo pip install virtualenv
结构化应用程序目录
我们将使用LargeApp的示例名称作为我们的应用程序文件夹。在内部,我们将有一个虚拟环境(即env)与应用程序包(即app)以及一些其他文件,如运行测试(开发)服务器的“run.py”和用于保存Flask配置。 结构 - 下面给出一个例子 - 是高度可扩展的,它被建成利用Flask和其他库提供的所有有用的工具。不要害怕,当你看到它,因为我们解释一切一步一步构建它。 目标示例结构:~/LargeApp
|-- run.py
|-- config.py
|__ /env # Virtual Environment
|__ /app # Our Application Module
|-- __init__.py
|-- /module_one
|-- __init__.py
|-- controllers.py
|-- models.py
|__ /templates
|__ /module_one
|-- hello.html
|__ /static
|__ ..
|__ .
|__ ..
|__ .
创建应用程序文件夹
让我们从创建我们需要的主文件夹开始。 顺序运行以下命令以执行任务:mkdir ~/LargeApp
mkdir ~/LargeApp/app
mkdir ~/LargeApp/app/templates
mkdir ~/LargeApp/app/static
我们目前的结构:
~/LargeApp
|__ /app # Our Application Module
|__ /templates
|__ /static
创建虚拟环境
使用虚拟环境带来了很多好处。强烈建议您为每个应用程序使用新的虚拟环境。将virtualenv文件夹保留在应用程序中是保持事物顺序和整齐的好方法。 运行以下安装 PIP创建一个新的虚拟环境。cd ~/LargeApp
virtualenv env
创建应用程序文件
在这一步中,我们将形成基本的应用程序文件,然后再继续使用模块和蓝图。 运行以下命令以创建基本应用程序文件:touch ~/LargeApp/run.py
touch ~/LargeApp/config.py
touch ~/LargeApp/app/__init__.py
我们目前的结构:
~/LargeApp
|-- run.py
|-- config.py
|__ /env # Virtual Environment
|__ /app # Our Application Module
|-- __init__.py
|__ /templates
|__ /static
安装Flask和应用程序依赖
一旦我们有一切就绪,开始我们用Flask开发,让我们下载并使用pip安装它。 运行以下命令以在虚拟环境env中安装Flask。cd ~/LargeApp
env/bin/pip install flask
env/bin/pip install flask-sqlalchemy
env/bin/pip install flask-wtf
注意:这里我们下载和
不激活的虚拟环境中安装Large Flask。然而,考虑到我们使用来自环境本身的pip,它实现了相同的任务。如果你使用一个激活的环境,你可以只使用pip。 就是这样!我们现在准备建立一个更大的Flask应用程序模块化使用蓝图。
使用模块和蓝图(组件)
模块基础
在这一点上,我们有我们的应用程序结构设置和它的依赖关系下载并准备好了。 我们的目标是模块化(即使用Flask的蓝图创建可重复使用的组件)所有可以逻辑分组的相关模块。 这样的示例可以是认证系统。将所有视图,控制器,模型和帮助器放在一个地方,以允许可重用性的方式设置,这使得这种结构化是维护应用程序同时提高生产力的一个很好的方式。 例如目标模块(组件)的结构(内部/app
):
# Our module example here is called *mod_auth*
# You can name them as you like as long as conventions are followed
/mod_auth
|-- __init__.py
|-- controllers.py
|-- models.py
|-- ..
|-- .
模块模板
为了支持模块化to-the-max,我们将构造“templates”文件夹以遵循上述约定,并包含一个新的文件夹 - 具有与模块相同或相似的相关名称 - 以包含其模板文件。 目标示例模板目录结构(内部LargeApp
):
/templates
|-- 404.html
|__ /auth
|-- signin.html
|-- signup.html
|-- forgot.html
|-- ..
|-- .
创建应用程序
在本节中,我们将继续在前面的步骤,移动到创建我们的第一个模块化组件(使用蓝图) 之前 ,我们的应用程序的实际编码开始:mod_auth
处理所有的认证相关程序(即签署式,签约机等)。
使用nano编辑“run.py”
nano ~/LargeApp/run.py
放置内容:
# Run a test server.
from app import app
app.run(host='0.0.0.0', port=8080, debug=True)
使用CTRL + X保存并退出,然后使用Y确认。
使用nano编辑“config.py”
nano ~/LargeApp/config.py
放置内容:
# Statement for enabling the development environment
DEBUG = True
# Define the application directory
import os
BASE_DIR = os.path.abspath(os.path.dirname(__file__))
# Define the database - we are working with
# SQLite for this example
SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(BASE_DIR, 'app.db')
DATABASE_CONNECT_OPTIONS = {}
# Application threads. A common general assumption is
# using 2 per available processor cores - to handle
# incoming requests using one and performing background
# operations using the other.
THREADS_PER_PAGE = 2
# Enable protection agains *Cross-site Request Forgery (CSRF)*
CSRF_ENABLED = True
# Use a secure, unique and absolutely secret key for
# signing the data.
CSRF_SESSION_KEY = "secret"
# Secret key for signing cookies
SECRET_KEY = "secret"
使用CTRL + X保存并退出,然后使用Y确认。
创建模块/组件
本节是定义本文核心的第一个主要步骤。在这里,我们将看到如何使用Flask的蓝图创建一个模块(即组件)。 什么是辉煌的这个是你的代码,具有易于维护的结合所提供的 可移植性和 可重用性 -您将在未来的感激经常是一个斗争回来,认识事物,因为他们留下了相当位。第1步:构造模块
正如我们所要做的,让我们一起创造我们的第一个模块(mod_auth
)的目录和文件,开始对他们的工作。
# Create the module directory inside the *app* module
mkdir ~/LargeApp/app/mod_auth
# Create where module's templates will reside
mkdir ~/LargeApp/app/templates/auth
# Create __init__.py to set the directory as a Python module
touch ~/LargeApp/app/mod_auth/__init__.py
# Create module's controllers and models etc.
touch ~/LargeApp/app/mod_auth/controllers.py
touch ~/LargeApp/app/mod_auth/models.py
touch ~/LargeApp/app/mod_auth/forms.py
# Create module's templates
touch ~/LargeApp/app/templates/auth/signin.html
# Create a HTTP 404 Error page
touch ~/LargeApp/app/templates/404.html
在这些操作之后,这是文件夹结构应该是什么样子:
~/LargeApp
|-- run.py
|-- config.py
|__ /env # Virtual Environment
|__ /app # Our Application Module
|-- __init__.py
|-- /mod_auth # Our first module, mod_auth
|-- __init__.py
|-- controllers.py
|-- models.py
|-- forms.py
|__ /templates
|-- 404.html
|__ /auth
|-- signin.html
|__ /static
第2步:定义模块数据模型
nano ~/LargeApp/app/mod_auth/models.py
放置以下不说明 - 示例 - 内容:
# Import the database object (db) from the main application module
# We will define this inside /app/__init__.py in the next sections.
from app import db
# Define a base model for other database tables to inherit
class Base(db.Model):
__abstract__ = True
id = db.Column(db.Integer, primary_key=True)
date_created = db.Column(db.DateTime, default=db.func.current_timestamp())
date_modified = db.Column(db.DateTime, default=db.func.current_timestamp(),
onupdate=db.func.current_timestamp())
# Define a User model
class User(Base):
__tablename__ = 'auth_user'
# User Name
name = db.Column(db.String(128), nullable=False)
# Identification Data: email & password
email = db.Column(db.String(128), nullable=False,
unique=True)
password = db.Column(db.String(192), nullable=False)
# Authorisation Data: role & status
role = db.Column(db.SmallInteger, nullable=False)
status = db.Column(db.SmallInteger, nullable=False)
# New instance instantiation procedure
def __init__(self, name, email, password):
self.name = name
self.email = email
self.password = password
def __repr__(self):
return '<User %r>' % (self.name)
使用CTRL + X保存并退出,然后使用Y确认。
第3步:定义模块表单
nano ~/LargeApp/app/mod_auth/forms.py
放置以下不说明 - 示例 - 内容:
# Import Form and RecaptchaField (optional)
from flask.ext.wtf import Form # , RecaptchaField
# Import Form elements such as TextField and BooleanField (optional)
from wtforms import TextField, PasswordField # BooleanField
# Import Form validators
from wtforms.validators import Required, Email, EqualTo
# Define the login form (WTForms)
class LoginForm(Form):
email = TextField('Email Address', [Email(),
Required(message='Forgot your email address?')])
password = PasswordField('Password', [
Required(message='Must provide a password. ;-)')])
使用CTRL + X保存并退出,然后使用Y确认。
第4步:定义应用程序控制器(视图)
nano ~/LargeApp/app/mod_auth/controllers.py
放置以下不说明 - 示例 - 内容:
# Import flask dependencies
from flask import Blueprint, request, render_template, \
flash, g, session, redirect, url_for
# Import password / encryption helper tools
from werkzeug import check_password_hash, generate_password_hash
# Import the database object from the main app module
from app import db
# Import module forms
from app.mod_auth.forms import LoginForm
# Import module models (i.e. User)
from app.mod_auth.models import User
# Define the blueprint: 'auth', set its url prefix: app.url/auth
mod_auth = Blueprint('auth', __name__, url_prefix='/auth')
# Set the route and accepted methods
@mod_auth.route('/signin/', methods=['GET', 'POST'])
def signin():
# If sign in form is submitted
form = LoginForm(request.form)
# Verify the sign in form
if form.validate_on_submit():
user = User.query.filter_by(email=form.email.data).first()
if user and check_password_hash(user.password, form.password.data):
session['user_id'] = user.id
flash('Welcome %s' % user.name)
return redirect(url_for('auth.home'))
flash('Wrong email or password', 'error-message')
return render_template("auth/signin.html", form=form)
保存并退出使用
CTRL+X
并与确认
Y
。
第5步:设置在“应用程序/ 初始化的.py”的应用
nano ~/LargeApp/app/__init__.py
放置内容:
# Import flask and template operators
from flask import Flask, render_template
# Import SQLAlchemy
from flask.ext.sqlalchemy import SQLAlchemy
# Define the WSGI application object
app = Flask(__name__)
# Configurations
app.config.from_object('config')
# Define the database object which is imported
# by modules and controllers
db = SQLAlchemy(app)
# Sample HTTP error handling
@app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
# Import a module / component using its blueprint handler variable (mod_auth)
from app.mod_auth.controllers import mod_auth as auth_module
# Register blueprint(s)
app.register_blueprint(auth_module)
# app.register_blueprint(xyz_module)
# ..
# Build the database:
# This will create the database file using SQLAlchemy
db.create_all()
使用CTRL + X保存并退出,然后使用Y确认。
第6步:创建模板
nano ~/LargeApp/app/templates/auth/signin.html
放置内容:
{% macro render_field(field, placeholder=None) %}
{% if field.errors %}
<div>
{% elif field.flags.error %}
<div>
{% else %}
<div>
{% endif %}
{% set css_class = 'form-control ' + kwargs.pop('class', '') %}
{{ field(class=css_class, placeholder=placeholder, **kwargs) }}
</div>
{% endmacro %}
<div>
<div>
<legend>Sign in</legend>
{% with errors = get_flashed_messages(category_filter=["error"]) %}
{% if errors %}
<div>
{% for error in errors %}
{{ error }}<br>
{% endfor %}
</div>
{% endif %}
{% endwith %}
{% if form.errors %}
<div>
{% for field, error in form.errors.items() %}
{% for e in error %}
{{ e }}<br>
{% endfor %}
{% endfor %}
</div>
{% endif %}
<form method="POST" action="." accept-charset="UTF-8" role="form">
{{ form.csrf_token }}
{{ render_field(form.email, placeholder="Your Email Address",
autofocus="") }}
{{ render_field(form.password, placeholder="Password") }}
<div>
<label>
<input type="checkbox" name="remember" value="1"> Remember Me
</label>
<a role="button" href="">Forgot your password?</a><span class="clearfix"></span>
</div>
<button type="submit" name="submit">Sign in</button>
</form>
</div>
</div>
使用CTRL + X保存并退出,然后使用Y确认。
注意:此模板文件是刚刚被用于演示目的创建了一个非常简单的和不完整的例子。 你是高度鼓励阅读
的Jinja2文档和使用基本文件建立自己的网站的模板。
第7步:查看您的模块在行动
创建我们的第一个模块后,是时候看到一切正在运行。 使用运行在开发服务器run.py
:
cd ~/LargeApp
env/bin/python run.py
这将启动在端口
8080举办的开发(即测试)服务器。 访问网址访问该模块:
http://[your droplet's IP]/auth/signin
虽然您将无法登录,但您可以通过输入一些示例数据或通过测试其验证程序来查看它。
:提交
OS Tezer