当前位置:   article > 正文

Web前端之Flask框架--任务清单管理系统(一:大型项目管理)_flask 项目前端

flask 项目前端

一、项目简介

任务清单管理系统采用 B/S 架构,基于 Linux 平台开发。采用轻量级的 Web 服务器 Nginx , 其后端实现建议采用基于 Python 语言的 Flask 开源 Web 框架,进而增强扩展性。
数据库采用关系型数据库 Mariadb ,前端的技术栈使用 Bootstrap 框架。该系统面向学生或者企业员工,提供任务添加、任务删除、任务完成标记, 任务搜索 ,可视化操作、数据实时展现等功能,目的在于轻松查看自己和他人的工作安排,合理规划手头任务。

1、项目功能

就像一般的 Todo List 应用一样, 实现了以下功能:

  • 管理数据库连接
  • 列出现有的待办事项
  • 创建新的待办事项
  • 检索单个待办事项
  • 编辑待办事项或标记待办事项
  • 删除待办事项

2、技术分析

1)、为什么选择Flask

Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。
Flask也被称为 “microframework” ,因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。
因此Flask是一个使用Python编写的轻量级Web应用框架。轻巧易扩展,而且够主流,有问题不怕找不到人问,最适合这种轻应用了。

2)、为什么选择Mariadb?

MariaDB 数据库管理系统MySQL的 一个分支,主要由开源社区在维护,采用 GPL 授权许可
MariaDB 的目的是完全兼容 MySQL ,包括 API命令行,使之能轻松成为 MySQL 的代替品。
MariaDB 虽然被视为 MySQL 数据库的替代品,但它在扩展功能、存储引擎以及一些新的功能改进方面都强过 MySQL 。而且从 MySQL 迁移到 MariaDB 也是非常简单的。

3)、为什么选择Bootstrap?

Bootstrap 是一个用于快速开发 Web 应用程序和网站的前端框架。Bootstrap 是基于 HTML、 CSS、JavaScript 的。具有移动设备优先、浏览器支持良好、容易上手、响应式设等。

二、大型项目管理

1、项目结构

多文件Flask程序的基本结构,如下图所示:
在这里插入图片描述

  • requirements.txt 列出了所有依赖包,便于在其他电脑中重新生成相同的虚拟环境;
  • config.py存储配置;
  • manage.py用于启动程序以及其他的程序任务。

2、配置文件选项

程序经常需要设定多个配置。一般分为开发、测试和生产环境, 它们使用不同的数据库,不会彼此影响。

import os
#获取当前文件的目录名,即获取当前项目的绝对路径
basedir=os.path.abspath(os.path.dirname(__file__))
#print(basedir)

class Config:
    """
    所有配置环境的基类,即不管是开发环境还是测试环境,配置相同的
    都写在Config里面,包含通用配置,称为配置环境的基类
    """
    SECRET_KEY=os.environ.get('SECRET_KEY') or 'westos secret key'
    #尤其在涉及(flask-WTF)登陆页面提交敏感信息时,一定要设置密钥
    SQLALCHEMY_COMMIT_ON_TEARDOM=True
    #是否自动提交、
    SQLALCHEMY_TRACK_MODIFICATIONS=True
    #是否追踪修改,从Flask-SQLALchemy文档中查看
    FLASK_MAIL_SUBJECT_PREFIX='安安的ToDolist'
    FLASK_MAIL_SENDER='792910452@qq.com'

    @staticmethod
    def init_app(app):
        """
        初始化app,后续用来添加第三方插件
        """
        pass

class DevelopmentConfig(Config):
    """
    开发环境配置
    """
    DEBUG=True
    #启用调试支持,服务器会在代码修改后自动载入,并在发生错误时提供一个相当有用的调试器
    MAIL_SERVER='smtp.qq.com'
    MAIL_PORT=587
    MAIL_USE_TLS=True
    #这里的os.environ.get()指从系统的环境中获取(),environ是与Linux配套的
    MAIL_USERNAME=os.environ.get('MAIL_USERNAME') or '792910452'
    MAIL_PASSWORD=os.environ.get('MAIL_PASSWORD') or '密码'
    SQLALCHEMY_DATABASE_URI='sqlite:///' + os.path.join(basedir,'data-dev.sqlite')
    #开发环境下的数据存放在当前文件下的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')

#为每一个配置环境起一个名字
config={
    'development':DevelopmentConfig,
    'testing':TestingConfig,
    'production':ProductionConfig,
    'default':DevelopmentConfig
    #默认是在开发环境中
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61

3、程序工厂函数

1) 为什么需要程序工厂函数?

在单个文件中开发程序很方便,但却有个很大的缺点,因为程序在全局作用域中创建,所以无法动态修改配置。运行脚本时,程序实例已经创建,再修改配置为时已晚。这一点对单元测试尤其重要,因为有时为了提高测试覆盖度,必须在不同的配置环境中运行程序

这个问题的解决方法是延迟创建程序实例,把创建过程移到可显式调用的工厂函数中。这种方法不仅可以给脚本留出配置程序的时间,还能够创建多个程序实例。

2) 如何实现程序工厂函数?

创建扩展类时不向构造函数传入参数,在之前创建的扩展对象上调用 init_app() 可以完成初始化过程。

3)代码详情
i、不使用程序工厂函数
#不使用程序工厂函数创建实例:
app = Flask(__name__)
bootstrap = Bootstrap(app)
mail = Mail(app)
  • 1
  • 2
  • 3
ii、使用程序工厂函数
"""
使用程序工厂函数,延迟创建程序实例
延迟创建flask应用
应用场景如下:
    1)测试:可以使用多个应用程序的实例。为每一种实例分配不同的配置,从而测试每一种不同的情况
    2)多个实例,要同时运行同一应用的不同版本。可以在你的Web服务器中创建多个实例并分配不同的配置
"""    
#程序工厂函数创建实例:
#首先实例化函数,再在需要的时候与实例结合从而创建实例,便于后续#代码修改维护

bootstrap = Bootstrap()
mail = Mail()
def create_app():
    app = Flask(__name__)
    bootstrap.init_app(app)
    mail.init_app(app)
    return app
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

app/__ init__.py文件详细代码如下:

from flask import Flask
from flask_bootstrap import Bootstrap
from flask_mail import Mail
from flask_sqlalchemy import SQLAlchemy

from config import config

bootstrap=Bootstrap()
db=SQLAlchemy()
mail=Mail()

def create_app(config_name='development'):
    """
    默认创建开发环境的app实例
    """
    app=Flask(__name__)
    app.config.from_object(config[config_name])
    #导入配置信息
    config[config_name].init_app(app)
    #初始化app
    bootstrap.init_app(app)
    db.init_app(app)
    mail.init_app(app)

    return app
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

4、蓝图:组件化开发

1)什么是蓝图?

Flask蓝图提供了模块化管理程序路由的功能,使程序结构清晰、简单易懂
假如说我们要为某所学校的每个人建立一份档案,一个很自然的优化方式就是这些档案如果能分类管理,就是说假如分为老师、学生、后勤人员等类别,那么后续查找和管理这些档案就方便清晰许多。Flask的蓝图就提供了类似“分类”的功能。

2)为什么使用蓝图?
  • 将不同的功能模块化
  • 构建大型应用
  • 优化项目结构
  • 增强可读性,易于维护
3)应用蓝图三部曲
i、蓝图的创建:app/auth/__ init__.py
1)创建蓝图
"""
from flask import Blueprint
#实例化一个蓝图对象,指定蓝图的名字和蓝图所在的位置
auth=Blueprint('auth',__name__)

#将路由与蓝本关联,一定要写在最后,防止循环导入
from . import views
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
ii、应用蓝图:app/auth/views.py

蓝图对象注册路由,指定静态文件夹,注册模板过滤器:app/auth/views.py

2)应用蓝图
"""
from app.auth import auth

@auth.route('/')
def index():
    return 'index'

@auth.route('/register')
def register():
    return 'register'

@auth.route('/login')
def login():
    return 'login'

@auth.route('/logout')
def logout():
    return 'logout'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
iii、注册蓝图对象:app/__ init__.py
#3)注册蓝图,将蓝图实例与app关联起来
from app.auth import auth
app.register_blueprint(auth,url_prefix='/auth')
  • 1
  • 2
4)任务清单蓝图的应用

todo蓝图,同auth蓝图一样

i、蓝图的创建:app/todo/__ init__.py
1)创建蓝图
"""
from flask import Blueprint

todo=Blueprint('todo',__name__)

from . import views
#将路由与蓝图关联起来
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
ii、应用蓝图:app/todo/views.py

蓝图对象上注册路由,指定静态文件夹,注册模版过滤器

2)应用蓝图
"""
from app.todo import todo

@todo.route('add')
def add():
    return 'todo add'

@todo.route('delete')
def delete():
    return 'todo delete'
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
iii、注册蓝图:app/__ init__.py
from app.todo import todo
app.register_blueprint(todo,url_prefix='/todo')
  • 1

5、启动脚本

顶级文件夹中的manage.py文件用于启动程序。

from app import create_app

def make_shell_context():
    return dict(app=app,name='anan',age=10)

if __name__ == '__main__':
    #app=create_app()
    #host='0.0.0.0'其中0表示任意,这个IP则表示我的IP地址在共享时可以和任意一个IP地址绑定在一起
    #app.run()
    from flask_script import Manager,Shell

    app=create_app()
    manager=Manager(app)

    #初始化 Flask-Script、Flask-Migrate和为Python shell定义的上下文
    manager.add_command('shell',Shell(make_context=make_shell_context))

    manager.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在terminal中通过下面命令执行脚本:

python manage.py runserver

    执行结果:
    在这里插入图片描述
    依次访问网址,如果访问可以显示相关信息,则成功

    • http://127.0.0.1:5000/auth/login
    • http://127.0.0.1:5000/auth/register
    • http://127.0.0.1:5000/todo/add
    • http://127.0.0.1:5000/todo/delete

    6、依赖包文件

    程序中必须包含一个requirement.txt文件,用于记录所有依赖包及其精确的版本号

    pip freeze >requirement.txt

      创建一个和当前环境相同的虚拟环境,并在其上运行以下命令(迭代的安装项目需要的第三方模块):

      pip install -r requirement.txt

        7、单元测试

        1)什么是单元测试?

        单元测试也称之为“模块测试”,是对程序设计中的最小单元——函数进行测试的一种方法,所谓测试,就是验证我们自己编写的方法能不能得到正确的结果,即将用方法得到的结果与真实结果进行比对,这就称之为测试

        2)如何实现单元测试

        python中有特别多的单元测试框架和工具,unittest,testtools,subunit,coverage,testrepository,nose,mox,mock,fixtures,discover等等,先不说如何写单元测试,光是怎么运行单元测试就有N多种方法。 unittest,作为标准python中的一个模块,是其它框架和工具的基础

        3)unittest核心概念及关系
        • TestCase 的实例就是一个测试用例。什么是测试用例呢?就是一个完整的测试流程包括测试前准备环境的搭建( setUp ),执行测试代码( run ),以及测试后环境的还原( tearDown )。单元测试( unittest )的本质也就在这里,一个测试用例是一个完整的测试单元,通过运行这个测试单元,可以对某一个问题进行验证
        • TestSuite是多个测试用例的集合,TestSuite也可以嵌套TestSuite 。
        • TestLoader 是用来将 TestCase 加载到 TestSuite 中的,其中有几个loadTestsFrom__() 方法,就是从各个地方寻找 TestCase ,创建它们的实例,然后add到 TestSuite 中,再返回一个TestSuite 实例。
        • TextTestRunner 是来执行测试用例的,其中的run(test)会执行TestSuite/TestCase 中的run(result)方法。
        • TextTestResult 保存测试的结果,包括运行了多少测试用例,成功了多少,失败了多少等信息。
          在这里插入图片描述
        4)测试范例
        #test/test_number.py
        import unittest
        from random import random
        
        
        class TestSequenceFunctions(unittest.TestCase):
            """
            setup()和tearDown()方法分别在各测试前后运行,并且名字以test_开头
            的函数都作为测试执行
            """
            def setUp(self) -> None:
                self.seq=[0,1,2,3,4,5,6,7]
        
            def test_choice_ok(self):
                item=random.choice(self.seq)
                result=item in self.seq
                self.assertTrue(result)
        
            def test_sample_ok(self):
                result=random.sample(self.seq,4)
                self.assertEqual(len(result),4)
        
            def tearDown(self) -> None:
                del self.seq
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23

        单独执行测试用例:

        python -m unittest test_number.py
          5)任务清单单元测试的应用

          第一个测试确保程序实例存在。第二个测试确保程序在测试配置中运行。
          若想把 tests 文件夹作为包使用,需要添加 tests/init.py 文件,不过这个文件可以为空,因为 unittest 包会扫描所有模块并查找测试。

          #test/test_basics.py
          import unittest
          from flask import current_app
          from app import create_app,db
          
          class BasicsTestCase(unittest.TestCase):
              """
              setup()和tearDown()方法分别在各测试前后运行,并且名字以test_
              开头的函数都作为测试执行
              """
              def setup(self):
                  """
                  在测试前创建一个测试环境:
                  1)使用测试配置创建程序
                  2)激活上下文,确保能在测试中使用current_app
                  3)创建一个全新的数据库,以备不时之需
                  """
                  self.app=create_app('testing')
                  self.app_context=self.app.app_context()
                  #将app_context与当前环境结合
                  self.app_context.push()
                  db.create_all()
          
              def tearDown(self) -> None:
                  db.session.remove()
                  db.drop_all()
          
              def test_app_exists(self):
                  """
                  测试当前app是否存在
                  """
                  self.assertFalse(current_app is None)
          
              def test_app_is_testing(self):
                  """
                  测试当前app是否为测试环境
                  """
                  self.assertTrue(current_app.config['TESTING'])
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37

          为了运行单元测试,在manage.py脚本中添加一个自定义命令。

          #manage.py
          @manager.command
          def tests():
              """
              执行Flask项目的测试用例
              """
              import unittest
              #将发现的所有app测试用例(testcase)绑定为测试集合(testsuite),使用testloader进行绑定
              tests=unittest.TestLoader().discover('tests')
              #verbosity是测试结果的复杂度,有0,1,2三种复杂度
              unittest.TextTestRunner(verbosity=2).run(tests)
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10

          单元测试使用下面命令运行:

          python manage.py tests

            8、项目需求文档

            文件 README.md , 建议包含项目介绍, 项目功能, 项目技术栈和项目最终演示效果。

            9、项目与GitHub

            1)Git
            1>什么是Git?

            Git(读音为/gɪt/)是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。
            Git 是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件

            2>为什么需要版本控制?
            i、在没有版本管理工具出现前

            试想一下,在没有版本管理工具出现之前,我们该如何实现代码的整合和备份管理?

            • 人工的方式拷贝目录,完成代码整合
            • 人工的方式备份历史文件
            • 人工整合,所以效率低
            • 整合周期长,频率低,造成软件维护的成本上升
            • 公共文件容易被覆盖,且难以定位
            ii、集中式版本控制(CVS)

            CVS和SVN式两个典型的代表
            在这里插入图片描述

            • 服务器自动完成代码的整合工作
            • 具备文件历史版本的管理能力和分支管理能力
            • 自动化集成,所以效率更高
            • 缺点是,客户端需要时刻跟服务端保持连接,所有的版本信息集中保存到服务
            iii、分布式版本控制(VCS)

            Git就是现在最火的代表
            在这里插入图片描述

            • git一样能自动完成代码整合和版本管理的能力
            • git具备更灵活的分支管理能力,可以方便定制我们的工作流程
            • 服务端和客户端都有完整的版本库
            • 客户端不需要一直连接服务器,脱离服务器也可以正常工作
            2)什么是Github?
            1>简介

            GitHub是一个面向开源及私有软件项目的托管平台,因为只支持git 作为唯一的版本库格式进行托管,故名GitHub。

            在这里插入图片描述

            • GitHub于2008年4月10日正式上线,除了Git代码仓库托管及基本的 Web管理界面以外,还提供了订阅、讨论组、文本渲染、在线文件编辑器、协作图谱(报表)、代码片段分享(Gist)等功能。目前,其注册用户已经超过350万,托管版本数量也是非常之多,其中不乏知名开源项目 Ruby on Rails、jQuery、python 等。
            • 2018年6月4日,微软宣布,通过75亿美元的股票交易收购代码托管平台GitHub。
            • 2019年05月,《个人电脑杂志》网站报道,GitHub正遭到一名黑客的入侵。据称,这名黑客先擦除代码资源库,然后向用户索要赎金,作为恢复数据的交换。
            2>Github功能

            Github从诞生之初,就有着另外两个非凡的使命:

            • 开源社交平台
            • 企业项目管理平台

            这两部分业务是最核心粘性最大的,也是Github的核心竞争力。

            截至2017年4月,GitHub报告有近2000万用户和5700万个项目,其中不乏知名开源项目Ruby on Rails、jQuery、python等。

            3)上传项目到Github
            • Github 上新建一个仓库 Repositories
              在这里插入图片描述

            • 填写相关Repositories仓库信息
              在这里插入图片描述

            • 出现下面页面,提示如何提交项目到Github上:
              在这里插入图片描述

            • 初始化项目为Git仓库,将项目文件添加到暂存区,提交到本地仓库,最终上传到远程仓库Github

            
            # 初始化项目为Git仓库 
            git init Initialized empty Git repository in /home/kiosk/Desktop/201905python/Todolist/.git/ # 将所有项目文件添加到暂存区 
            git add * 
            # 提交到本地仓库 
            git commit -m "Flask任务清单管理系统(一): 大型项目结构化管理" 
            # 添加一个新的远程仓库, 第一次需要, 后面的不需要添加. 
            git remote add origin https://github.com/lvah/TodoList.git 
            # 上传项目至远程仓库`Github 
            git push -u origin master
            • 1
            • 2
            • 3
            • 4
            • 5
            • 6
            • 7
            • 8
            • 9
            4)Git常用命令流程图

            在这里插入图片描述

            5)Git命令快速查找手册

            在这里插入图片描述

            声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/185704?site
            推荐阅读
            相关标签
              

            闽ICP备14008679号