前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >带你认识 flask 优化应用结构

带你认识 flask 优化应用结构

作者头像
公众号---人生代码
发布于 2019-11-24 07:23:55
发布于 2019-11-24 07:23:55
1.5K00
代码可运行
举报
文章被收录于专栏:人生代码人生代码
运行总次数:0
代码可运行

01

目前的局限性

目前状态下的应用有两个基本问题。如果你观察应用的组织方式,你会注意到有几个不同的子系统可以被识别,但支持它们的代码都混合在了一起,没有任何明确的界限。我们来回顾一下这些子系统是什么:

  • 用户认证子系统,包括app/routes.py中的一些视图函数,app/forms.py中的一些表单,app/templates中的一些模板以及app/email.py中的电子邮件支持。
  • 错误子系统,它在app/errors.py中定义了错误处理程序并在app/templates中定义了模板。
  • 核心应用功能,包括显示和撰写用户动态,用户个人主页和关注以及用户动态的实时翻译,这些功能遍布大多数应用模块和模板。

思考这三个子系统以及它们组织的方式,你可能会注意到这样一个模式。到目前为止,我一直遵循的组织逻辑是不同的应用功能归属到其专属的模块。这些模块之中,一个用于视图函数,一个用于Web表单,一个用于错误,一个用于电子邮件,一个目录用于存放HTML模板等等。虽然这是一个对小项目有意义的组织结构,但是一旦项目开始增长,它往往会使其中的一些模块变得非常大而且杂乱无章。

要想清晰地看到问题的一种方法,是思考如何通过尽可能多地重复使用这一项目来开始第二个项目。例如,用户身份验证部分应该在其他应用中也能运行良好,但如果你想按原样使用该代码,则必须进入多个模块并将相关部分复制/粘贴到新项目的新文件中。看到这是多么不方便了吗?如果这个项目将所有与认证相关的文件从应用的其余部分中分离出来,会不会更好?Flask的blueprints功能有助于实现更实用的组织结构,从而更轻松地重用代码。

还有第二个问题,虽然它不太明显。Flask应用实例在app/__init__.py中被创建为一个全局变量,然后又被很多应用模块导入。虽然这本身并不是问题,但将应用实例作为全局变量可能会使某些情况复杂化,特别是与测试相关的情景。想象一下你想要在不同的配置下测试这个应用。由于应用被定义为全局变量,实际上没有办法使用不同配置变量来实例化的两个应用实例。另一种糟心的情况是,所有测试都使用相同的应用,因此测试可能会对应用进行更改,就会影响稍后运行的其他测试。理想情况下,你希望所有测试都在原始应用实例上运行的。

你可以在tests.py模块中看到我正在使用的应用实例化之后修改配置的技巧,以指示测试时使用内存数据库而不是默认的SQLite数据库。我真的没有其他办法来更改已配置的数据库,因为在测试开始时已经创建和配置了应用。对于这种特殊情况,对已配置的应用实例修改配置似乎可以运行,但在其他情况下可能不会,并且在任何情况下,这是一种不推荐的做法,因为这么做可能会导致提示晦涩并且难以找到BUG。

更好的解决方案是不将应用设置为全局变量,而是使用应用工厂函数在运行时创建它。 这将是一个接受配置对象作为参数的函数,并返回一个配置完毕的Flask应用实例。如果我能够通过应用工厂函数来修改应用,那么编写需要特殊配置的测试会变得很容易,因为每个测试都可以创建它各自的应用。

在本章中,我将通过为上面提到的三个子系统重构应用来介绍blueprints。展示更改的详细列表有些不切实际,因为几乎应用中每个文件都有少许变化,所以我将讨论重构的步骤,然后你可以下载更改后的应用。

02

Blueprints

在Flask中,blueprint是代表应用子集的逻辑结构。blueprint可以包括路由,视图函数,表单,模板和静态文件等元素。如果在单独的Python包中编写blueprint,那么你将拥有一个封装了应用特定功能的组件。

Blueprint的内容最初处于休眠状态。为了关联这些元素,blueprint需要在应用中注册。在注册过程中,需要将添加到blueprint中的所有元素传递给应用。因此,你可以将blueprint视为应用功能的临时存储,以帮助组织代码。

03

错误处理 blueprints

我创建的第一个blueprint用于封装对错误处理程序的支持。该blueprint的结构如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
app/    errors/                             <-- blueprint package        __init__.py                     <-- blueprint creation        handlers.py                     <-- error handlers    templates/        errors/                         <-- error templates            404.html            500.html    __init__.py                         <-- blueprint registration

实质上,我所做的是将app/errors.py模块移动到app/errors/handlers.py中,并将两个错误模板移动到app/templates/errors中,以便将它们与其他模板分开。我还必须在两个错误处理程序中更改render_template()调用以使用新的errors模板子目录。之后,我将blueprint创建添加到app/errors/__init__.py模块,并在创建应用实例之后,将blueprint注册到app/__init__.py

我必须提一下,Flask blueprints可以为自己的模板和静态文件配置单独的目录。我已决定将模板移动到应用模板目录的子目录中,以便所有模板都位于一个层次结构中,但是如果你希望在blueprint中包含属于自己的模板,这也是支持的。例如,如果向Blueprint()构造函数添加template_folder='templates'参数,则可以将错误blueprint的模板存储在app/errors/templates目录中。

创建blueprint与创建应用非常相似。这是在blueprint的___init__.py模块中完成的:

app/errors/__init__.py:错误blueprint

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from flask import Blueprint
bp = Blueprint('errors', __name__)
from app.errors import handlers

Blueprint类获取blueprint的名称,基础模块的名称(通常在Flask应用实例中设置为__name__)以及一些可选参数(在这种情况下我不需要这些参数)。Blueprint对象创建后,我导入了handlers.py模块,以便其中的错误处理程序在blueprint中注册。该导入位于底部以避免循环依赖。

handlers.py模块中,我放弃使用@app.errorhandler装饰器将错误处理程序附加到应用程序,而是使用blueprint的@bp.app_errorhandler装饰器。尽管两个装饰器最终都达到了相同的结果,但这样做的目的是试图使blueprint独立于应用,使其更具可移植性。我还需要修改两个错误模板的路径,因为它们被移动到了新errors子目录。

完成错误处理程序重构的最后一步是向应用注册blueprint:

app/__init__.py:向应用注册错误blueprint

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
app = Flask(__name__)
# ...
from app.errors import bp as errors_bpapp.register_blueprint(errors_bp)
# ...
from app import routes, models  # <-- remove errors from this import!

为了注册blueprint,将使用Flask应用实例的register_blueprint()方法。在注册blueprint时,任何视图函数,模板,静态文件,错误处理程序等均连接到应用。我将blueprint的导入放在app.register_blueprint()的上方,以避免循环依赖

04

用户认证 blueprints

将应用的认证功能重构为blueprint的过程与错误处理程序的过程非常相似。以下是重构为blueprint的目录层次结构:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
app/    auth/                               <-- blueprint package        __init__.py                     <-- blueprint creation        email.py                        <-- authentication emails        forms.py                        <-- authentication forms        routes.py                       <-- authentication routes    templates/        auth/                           <-- blueprint templates            login.html            register.html            reset_password_request.html            reset_password.html    __init__.py

为了创建这个blueprint,我必须将所有认证相关的功能移到为blueprint创建的新模块中。这包括一些视图函数,Web表单和支持功能,例如通过电子邮件发送密码重设token的功能。我还将模板移动到一个子目录中,以将它们与应用的其余部分分开,就像我对错误页面所做的那样。

在blueprint中定义路由时,使用@bp.route装饰器来代替@app.route装饰器。在url_for()中用于构建URL的语法也需要进行更改。对于直接附加到应用的常规视图函数,url_for()的第一个参数是视图函数名称。但当在blueprint中定义路由时,该参数必须包含blueprint名称和视图函数名称,并以句点分隔。因此,我不得不用诸如url_for('auth.login')的代码替换所有出现的url_for('login')代码,对于其余的视图函数也是如此。

注册auth blueprint到应用时,我使用了些许不同的格式:

app/__init__.py:注册用户认证blueprint到应用

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# ...from app.auth import bp as auth_bpapp.register_blueprint(auth_bp, url_prefix='/auth')# ...

在这种情况下,register_blueprint()调用接收了一个额外的参数,url_prefix。这完全是可选的,Flask提供了给blueprint的路由添加URL前缀的选项,因此blueprint中定义的任何路由都会在其完整URL中获取此前缀。在许多情况下,这可以用来当成“命名空间”,它可以将blueprint中的所有路由与应用或其他blueprint中的其他路由分开。对于用户认证,我认为让所有路由以 /auth 开头很不错,所以我添加了该前缀。所以现在登录URL将会是 http://localhost:5000/auth/login 。因为我使用url_for()来生成URL,所有URL都会自动合并前缀

05

主应用 blueprints

第三个blueprint包含核心应用逻辑。重构这个blueprint和前两个blueprint的过程一样。我给这个blueprint命名为main,因此所有引用视图函数的url_for()调用都必须添加一个main.前缀。鉴于这是应用的核心功能,我决定将模板留在原来的位置。这不会有什么问题,因为我已将其他两个blueprint中的模板移动到子目录中了

06

应用工厂模式

正如我在本章的介绍中所提到的,将应用设置为全局变量会引入一些复杂性,主要是以某些测试场景的局限性为形式。在我介绍blueprint之前,应用必须是一个全局变量,因为所有的视图函数和错误处理程序都需要使用来自app的装饰器来修饰,比如@app.route。但是现在所有的路由和错误处理程序都被转移到了blueprint中,因此保持应用全局性的理由就不够充分了。

所以我要做的是添加一个名为create_app()的函数来构造一个Flask应用实例,并消除全局变量。转换并非容易,我不得不理清一些复杂的东西,但我们先来看看应用工厂函数:

app/__init__.py:应用工厂函数

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
# ...db = SQLAlchemy()migrate = Migrate()login = LoginManager()login.login_view = 'auth.login'login.login_message = _l('Please log in to access this page.')mail = Mail()bootstrap = Bootstrap()moment = Moment()babel = Babel()
def create_app(config_class=Config):    app = Flask(__name__)    app.config.from_object(config_class)
    db.init_app(app)    migrate.init_app(app, db)    login.init_app(app)    mail.init_app(app)    bootstrap.init_app(app)    moment.init_app(app)    babel.init_app(app)
    # ... no changes to blueprint registration
    if not app.debug and not app.testing:        # ... no changes to logging setup
    return app

你已经看到,大多数Flask插件都是通过创建插件实例并将应用作为参数传递来初始化的。当应用不再作为全局变量时,有一种替代模式,插件分成两个阶段进行初始化。插件实例首先像前面一样在全局范围内创建,但没有参数传递给它。这会创建一个未附加到应用的插件实例。当应用实例在工厂函数中创建时,必须在插件实例上调用init_app()方法,以将其绑定到现在已知的应用。

在初始化期间执行的其他任务保持不变,但会被移到工厂函数而不是在全局范围内。这包括blueprint和日志配置的注册。请注意,我在条件中添加了一个not app.testing子句,用于决定是否启用电子邮件和文件日志,以便在单元测试期间跳过所有这些日志记录。由于在配置中TESTING变量在单元测试时会被设置为True,因此app.testing标志在运行单元测试时将变为True

那么谁来调用应用程工厂函数呢?最明显使用此函数的地方是处于顶级目录的microblog.py脚本,它是唯一会将应用设置为全局变量的模块。另一个调用该工厂函数的地方是tests.py,我将在下一节中更详细地讨论单元测试。

正如我上面提到的,大多数对app的引用都是随着blueprint的引入而消失的,但是我仍然需要解决代码中的一些问题。例如,app/models.pyapp/translate.pyapp/main/routes.py模块都引用了app.config。幸运的是,Flask开发人员试图使视图函数很容易地访问应用实例,而不必像我一直在做的那样导入它。Flask提供的current_app变量是一个特殊的“上下文”变量,Flask在分派请求之前使用应用初始化该变量。你之前已经看到另一个上下文变量,即存储当前语言环境的g变量。这两个变量,以及Flask-Login的current_user和其他一些你还没有看到的东西,是“魔法”变量,因为它们像全局变量一样工作,但只能在处理请求期间且在处理它的线程中访问。

用Flask的current_app变量替换app就不需要将应用实例作为全局变量导入。通过简单的搜索和替换,我可以毫无困难地用current_app.config替换对app.config的所有引用。

app/email.py模块提出了一个更大的挑战,所以我必须使用一个小技巧:

app/email.py:将应用实例传递给另一个线程。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from flask import current_app
def send_async_email(app, msg):    with app.app_context():        mail.send(msg)
def send_email(subject, sender, recipients, text_body, html_body):    msg = Message(subject, sender=sender, recipients=recipients)    msg.body = text_body    msg.html = html_body    Thread(target=send_async_email,           args=(current_app._get_current_object(), msg)).start()

send_email()函数中,应用实例作为参数传递给后台线程,后台线程将发送电子邮件而不阻塞主应用程序。在作为后台线程运行的send_async_email()函数中直接使用current_app将不会奏效,因为current_app是一个与处理客户端请求的线程绑定的上下文感知变量。在另一个线程中,current_app没有赋值。直接将current_app作为参数传递给线程对象也不会有效,因为current_app实际上是一个代理对象,它被动态地映射到应用实例。因此,传递代理对象与直接在线程中使用current_app相同。我需要做的是访问存储在代理对象中的实际应用程序实例,并将其作为app参数传递。 current_app._get_current_object()表达式从代理对象中提取实际的应用实例,所以它就是我作为参数传递给线程的。

另一个棘手的模块是app/cli.py,它实现了一些用于管理语言翻译的快捷命令。在这种情况下,current_app变量不起作用,因为这些命令是在启动时注册的,而不是在处理请求期间(这是唯一可以使用current_app的时间段)注册的。为了在这个模块中删除对app的引用,我使用了另一个技巧,将这些自定义命令移动到一个将app实例作为参数的register()函数中:

app/cli.py:注册自定义应用命令。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import osimport click
def register(app):    @app.cli.group()    def translate():        """Translation and localization commands."""        pass
    @translate.command()    @click.argument('lang')    def init(lang):        """Initialize a new language."""        # ...
    @translate.command()    def update():        """Update all languages."""        # ...
    @translate.command()    def compile():        """Compile all languages."""        # ...

然后我从microblog.py中调用这个register()函数。以下是完成重构后的microblog.py

microblog.py:重构后的主应用模块。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from app import create_app, db, clifrom app.models import User, Post
app = create_app()cli.register(app)
@app.shell_context_processordef make_shell_context():    return {'db': db, 'User': User, 'Post' :Post}

07

单元测试改进

正如我在本章开头所暗示的,到目前为止,我所做的很多工作都是为了改进单元测试工作流程。在运行单元测试时,要确保应用的配置方式不会污染开发资源(如数据库)。

tests.py的当前版本采用了应用实例化之后修改配置的技巧,这是一种危险的做法,因为并不是所有类型的更改都会在修改之后才生效。我想要的是有机会在添加到应用之前指定我想要的测试配置项。

create_app()函数现在接受一个配置类作为参数。默认情况下,使用在config.py中定义的Config类,但现在我可以通过将新类传递给工厂函数来创建使用不同配置的应用实例。下面是一个适用于我的单元测试的示例配置类:

tests.py:测试配置。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from config import Config
class TestConfig(Config):    TESTING = True    SQLALCHEMY_DATABASE_URI = 'sqlite://'

我在这里做的是创建应用的Config类的子类,并覆盖SQLAlchemy配置以使用内存SQLite数据库。我还添加了一个TESTING属性,并设置为True,我目前不需要该属性,但如果应用需要确定它是否在单元测试下运行,它就派上用场了。

你一定还记得,我的单元测试依赖于setUp()tearDown()方法,它们由单元测试框架自动调用,以创建和销毁每次测试运行的环境。我现在可以使用这两种方法为每个测试创建和销毁一个测试专用的应用:

tests.py:为每次测试创建一个应用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class UserModelCase(unittest.TestCase):    def setUp(self):        self.app = create_app(TestConfig)        self.app_context = self.app.app_context()        self.app_context.push()        db.create_all()
    def tearDown(self):        db.session.remove()        db.drop_all()        self.app_context.pop()

新的应用将存储在self.app中,但光是创建一个应用不足以使所有的工作都成功。思考创建数据库表的db.create_all()语句。 db实例需要注册到应用实例,因为它需要从app.config获取数据库URI,但是当你使用应用工厂时,应用就不止一个了。那么db如何关联到我刚刚创建的self.app实例呢?

答案在application context中。还记得current_app变量吗?当不存在全局应用实例导入时,该变量以代理的形式来引用应用实例。这个变量在当前线程中查找活跃的应用上下文,如果找到了,它会从中获取应用实例。如果没有上下文,那么就没有办法知道哪个应用实例处于活跃状态,所以current_app就会引发一个异常。下面你可以看到它是如何在Python控制台中工作的。这需要通过运行python启动,因为flask shell命令会自动激活应用程序上下文以方便使用。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
>>> from flask import current_app>>> current_app.config['SQLALCHEMY_DATABASE_URI']Traceback (most recent call last):    ...RuntimeError: Working outside of application context.
>>> from app import create_app>>> app = create_app()>>> app.app_context().push()>>> current_app.config['SQLALCHEMY_DATABASE_URI']'sqlite:////home/miguel/microblog/app.db'

这就是秘密所在!在调用你的视图函数之前,Flask推送一个应用上下文,它会使current_appg生效。当请求完成时,上下文将与这些变量一起被删除。为了使db.create_all()调用在单元测试setUp()方法中工作,我为刚刚创建的应用程序实例推送了一个应用上下文,这样db.create_all()可以使用 current_app.config知道数据库在哪里。然后在tearDown()方法中,我弹出上下文以将所有内容重置为干净状态。

你还应该知道,应用上下文是Flask使用的两种上下文之一,还有一个请求上下文,它更具体,因为它适用于请求。在处理请求之前激活请求上下文时,Flask的requestsession以及Flask-Login的current_user变量才会变成可用状态。

08

环境变量

正如构建此应用时你所看到的,在启动服务器之前,有许多配置选项取决于在环境中设置的变量。这包括密钥、电子邮件服务器信息、数据库URL和Microsoft Translator API key。你可能会和我一样觉得,这很不方便,因为每次打开新的终端会话时,都需要重新设置这些变量。

译者注:可以通过将环境变量设置到开机启动中,来保持它们在该计算机中的所有终端中都生效。

应用依赖大量环境变量的常见处理模式是将这些变量存储在应用根目录中的 .env 文件中。应用在启动时会从此文件中导入变量,这样就不需要你手动设置这些变量了。

有一个支持 .env 文件的Python包,名为python-dotenv。所以让我们安装这个包:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(venv) $ pip install python-dotenv

由于config.py模块是我读取所有环境变量的地方,因此我将在创建Config类之前导入 .env 文件,以便在构造类时设置变量:

config.py:导入 .env 文件中的环境变量。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
import osfrom dotenv import load_dotenv
basedir = os.path.abspath(os.path.dirname(__file__))load_dotenv(os.path.join(basedir, '.env'))
class Config(object):    # ...

现在你可以创建一个 .env 文件并在其中写入应用所需的所有环境变量了。不要将 .env 文件加入到源代码版本控制中,这非常重要。否则,一旦你的密码和其他重要信息上传到远程代码库中后,你就会后悔莫及。

.env文件可以用于所有配置变量,但是不能用于Flask命令行的FLASK_APPFLASK_DEBUG环境变量,因为它们在应用启动的早期(应用实例和配置对象存在之前)就被使用了。

以下示例显示了 .env 文件,该文件定义了一个安全密钥,将电子邮件配置为在本地运行的邮件服务器的25端口上,并且不进行身份验证,设置Microsoft Translator API key,使用数据库配置的默认值:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
SECRET_KEY=a-really-long-and-unique-key-that-nobody-knowsMAIL_SERVER=localhostMAIL_PORT=25MS_TRANSLATOR_KEY=<your-translator-key-here>

09

依赖文件

此时我已经在Python虚拟环境中安装了一定数量的软件包。如果你需要在另一台机器上重新生成你的环境,将无法记住你必须安装哪些软件包,所以一般公认的做法是在项目的根目录中写一个requirements.txt文件,列出所有依赖的包及其版本。生成这个列表实际上很简单:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(venv) $ pip freeze > requirements.txt

pip freeze命令将安装在虚拟环境中的所有软件包以正确的格式输入到requirements.txt文件中。现在,如果你需要在另一台计算机上创建相同的虚拟环境,无需逐个安装软件包,可以直接运行一条命令实现:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
(venv) $ pip install -r requirements.txt
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CryptoCode 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
慕课网Flask高级编程实战-3.蓝图、模型与CodeFirst
应该讲一些初始化工作,放在对应层级的包的初始化文件 __init__.py 中。比如Flask核心应用app对象初始化应该放在应用层级app包的 __init__.py 中。蓝图的初始化,应该放在对应蓝图层级web包的__init__.py中,并且所有蓝图对应的试图函数都应该放在web目录下
Meet相识
2018/09/12
1.2K0
慕课网Flask高级编程实战-3.蓝图、模型与CodeFirst
Flask-蓝图、模型与CodeFirs
db.create_all(app=app),这样就可以了,在数据库中就可以看到表了
py3study
2020/01/19
5890
Flask-蓝图、模型与CodeFirs
python 生成flask结构 常用
config=""" import os basedir = os.path.abspath(os.path.dirname(file)) class Config: SECRET_KEY ='hard to guess string' SQLALCHEMY_COMMIT_ON_TEARDOWN = True FLASKY_MAIL_SUBJECT_PREFIX = '[Flasktest]' FLASKY_MAIL_SENDER = '13285921108@163.com' FLASKY_ADMIN = 'huangat' @staticmethod def init_app(app): pass class DevelopmentConfig(Config): DEBUG = True MAIL_SERVER = 'mail.163.com' MAIL_PORT = 587 MAIL_USE_TLS = True MAIL_USERNAME = os.environ.get('13285921108') MAIL_PASSWORD = os.environ.get('MAIL_PASSWORD') SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data-dev.sqlite') class TestingConfig(Config): TESTING = True SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data-test.sqlite') class ProductionConfig(Config): SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
用户5760343
2019/07/07
6270
经典案例之某新闻网站的实现
技术实现:python3.x+Flask+第三方sdk(云通讯+七牛云)+部署(阿里云)
小闫同学啊
2019/07/18
9190
经典案例之某新闻网站的实现
Flask的Blueprints和Views
Flask的view函数是用来对请求作出响应的。单个URL能匹配到单个View,那么多个类似的URL,比如:
dongfanger
2021/11/30
7220
flask flask-script自定义指令(flask 50)
from flask import Flask,render_template from views.admin import admin_bp from views.auth import auth_bp from views.blog import blog_bp from settings import config from extensions import bootstrap,db,login_manager,csrf,ckeditor,mail,moment,toolbar,migrate import os from flask_wtf.csrf import CSRFError from fakes import fake_admin, fake_categories, fake_posts, fake_comments from flask_script import Manager
用户5760343
2019/08/14
3470
Flask 学习-64.current_app的使用与应用上下文(AppContext)
前言 在很多框架里面都提到一个词:上下文(Context),比如django里面的request 就是一个请求上下文对象。 flask 里面 current_app 用于获取应用app对象。 上下文(Context) 什么是上下文(Context) 维持一段程序正常运行的所需要的外部变量的值的集合,叫做上下文(context)。 详细描述: 每一段程序都有很多外部变量。只有像Add这种简单的函数才是没有外部变量的。 一旦你的一段程序有了外部变量,这段程序就不能独立完整的运行。 你为了使他们运行,就要给所有的
上海-悠悠
2022/09/19
2.7K0
Flask 学习-64.current_app的使用与应用上下文(AppContext)
Flask内置命令行工具—CLI
flask命令在Flask库安装后可使用,使用前需要正确配置FLASK_APP环境变量以告知用户程序所在位置。不同平台设置方式有所不同。
枇杷李子橙橘柚
2019/05/26
3K0
Python Web Flask源码解读(四)——全局变量
Flask中全局变量有current_app、request、g和session。不过需要注意的是虽然标题是写着全局变量,但实际上这些变量都跟当前请求的上下文环境有关,下面一起来看看。
阳仔
2019/08/23
3.4K0
带你认识 flask 错误处理
在Flask应用中爆发错误时会发生什么?得到答案的最好的方法就是亲身体验一下。启动应用,并确保至少有两个用户注册,以其中一个用户身份登录,打开个人主页并单击“编辑”链接。在个人资料编辑器中,尝试将用户名更改为已经注册的另一个用户的用户名,boom!(爆炸声) 这将带来一个可怕的“Internal Server Error”页面:
公众号---人生代码
2019/11/12
2.2K0
Flask web项目目录解读
在 Python 中,Flask 项目的目录结构可以根据项目的复杂度和规模有所不同。以下是一个基础的 Flask 项目目录结构示例,适用于中小型web项目:
空洞的盒子
2024/08/09
1.4K1
Flask 项目工程拆分
一、蓝本 blueprint 说明 当我们的代码越来越复杂时,将所有的视图函数放在一个文件中很明显时不合适的;如果能够根据功能模块进行划分,存储在不同的文件中,蓝本就是为解决此问题而生的 使用 创建user.py <span class="hljs-keyword">from</span> flask <span class="hljs-keyword">import</span> Blueprint <span class="hljs-comment"># 创建蓝本对象</span> user
星哥玩云
2022/09/14
3130
Flask项目发布流程
本文继续对Flask官方教程进行学习,我就直接跳过Templates、Static Files、Blog Blueprint三小节了,因为基本不会在实际项目中用到这些技术,有时间多学习下前端才是。这篇文章把Make the Project Installable、Test Coverage、Deploy to Production这三小节汇总来学习。我觉得这是官方给出的一个Flask项目发布流程,如下图所示:
dongfanger
2021/12/02
1K0
Flask项目发布流程
AutoLine源码分析之Flask初始化模块
下面我们看下在manage.py中如何调用create_app来初始化全局flask运行环境的。
苦叶子
2018/07/25
5970
AutoLine源码分析之Flask初始化模块
Flask框架入门完全指南
Flask作为Python最受欢迎的轻量级Web框架,以"微核心+可扩展"的设计哲学著称。其核心代码仅约2000行,却支持通过扩展实现完整Web开发功能。这种设计使得开发者可以:
DevKevin
2025/02/17
2860
python flask web基本结构 常用
|-flasky |-app/ |-templates/ |-static/ |-main/ |-init.py |-errors.py |-forms.py |-views.py |-init.py |-email.py |-models.py |-migrations/ |-tests/ |-init.py |-test*.py |-venv/ |-requirements.txt |-config.py |-manage.py
用户5760343
2019/07/05
7740
带你认识 flask 全文搜索
对于全文搜索的支持不像关系数据库那样是标准化的。有几种开源的全文搜索引擎:Elasticsearch,Apache Solr,Whoosh,Xapian,Sphinx等等,如果这还不够,常用的数据库也可以像我上面列举的那些专用搜索引擎一样提供搜索服务。 SQLite,MySQL和PostgreSQL都提供了对搜索文本的支持,以及MongoDB和CouchDB等NoSQL数据库当然也提供这样的功能。
公众号---人生代码
2019/11/24
3.6K0
flask-利用Blueprint、flask_restful编写一个后端测试项目
之前用flask写了一个简单的web数据平台,那会儿刚学flask,所以是用单脚本写的,把所有逻辑都放到了app.py文件中。
冰霜
2022/03/15
8150
flask-利用Blueprint、flask_restful编写一个后端测试项目
《Flask Web开发》学习笔记
  前言:想熟练掌握一门web框架,为以后即将诞生的测试工具集做准备。为什么选择flask要做熟练掌握的一门框架,而不是其他的,最主要的原因是可以随意定制。
py3study
2020/01/20
1.7K0
Flask 学习-19.配置管理flask_sqlalchemy 和 flask_migrate
前言 前面讲了项目中使用config.py 可以管理开发、生产、测试等环境的配置,这篇继续学习在项目中添加flask_sqlalchemy 和 flask_migrate 的配置 环境准备 先pip安装flask_sqlalchemy 和 flask_migrate pip install flask_sqlalchemy pip install flask_migrate flask_sqlalchemy是封装了sqlalchemy 实现 ORM 操作数据库,flask_migrate 模块可以实现数据迁
上海-悠悠
2022/09/02
7060
Flask 学习-19.配置管理flask_sqlalchemy 和 flask_migrate
相关推荐
慕课网Flask高级编程实战-3.蓝图、模型与CodeFirst
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档