热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

day054Flask_数据库,其他

今天的主要内容有:数据库迁移;邮件扩展,蓝图,单元测试以及RESTful。数据库迁移在命令行使用Flask-Migrat

今天的主要内容有:数据库迁移;邮件扩展,蓝图,单元测试以及RESTful。


数据库迁移


  • 在命令行使用Flask-Migrate包中的命令对数据库进行增删改的操作
  • 需要先在虚拟环境中安装Flask-Migigrate

    pip install flask-migrate

  • 需要使用flask-migrate中的Migrate类以及MigrateCommand类,前者负责关联app和数据库实例,后者包含了一些执行命令

  • 为什么要使用flask-migrate迁移数据库操作

    • 之前的操作是先用drop_all()将数据库清空,再用create_all()更新新的数据到数据库,这样操作是危险的,且没有记录。在实际工作中,大多数是更新数据库,但是不会删除数据
    • 可以保存每一次操作记录,像git一样记录每一次迁移信息
    • 可以返回之前的版本,也可以从旧的版本升级到新的版本,注意从旧版本升级到新的版本数据可能会丢失,所以尽量只执行更新数据库命令(db upgrade)

迁移步骤


  • 配置阶段

    1. 从flask_migrate包中导入Migrate,MigrateCommand

    from flask_migrate import Migrate,MigrateCommand

    1. 将flask的实例和qlalchemy数据库实例用Migrate()关联起来

    migrate = Migrate(app,db)

    1. 在flask_Script中添加一个db命令

    manager.add_command('db',MigrateCommand)

  • 执行阶段

    1. 初始化化Migrations文件夹

    python database.py db init

    1. 创建迁移文件

    python database.py db migrate -m 'initial migration'

    1. 执行迁移

    python database.py db upgrade

  • 完整代码

#coding=utf-8
from flask import Flaskfrom flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate,MigrateCommand
from flask_script import Shell,Managerapp = Flask(__name__)
manager = Manager(app)app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:mysql@127.0.0.1:3306/Flask_test'
db = SQLAlchemy(app)#第一个参数是Flask的实例,第二个参数是Sqlalchemy数据库实例
migrate = Migrate(app,db) #manager是Flask-Script的实例,这条语句在flask-Script中添加一个db命令
manager.add_command('db',MigrateCommand)#定义模型Role
class Role(db.Model):# 定义表名__tablename__ = 'roles'# 定义列对象id = db.Column(db.Integer, primary_key=True)name = db.Column(db.String(64), unique=True)user = db.relationship('User', backref='role')#repr()方法显示一个可读字符串,def __repr__(self):return 'Role:'.format(self.name)#定义用户
class User(db.Model):__talbe__ = 'users'id = db.Column(db.Integer, primary_key=True)username = db.Column(db.String(64), unique=True, index=True)#设置外键role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))def __repr__(self):return 'User:'.format(self.username)if __name__ == '__main__':manager.run()

  • 命令行迁移命令

  • 初始化迁移文件夹


  • 生成迁移文件


  • 迁移文件


  • 迁移完成后,数据库结果

这里写图片描述


返回之前的版本


  • 可以根据history命令找到版本号,然后传给downgrade命令
  • 找到版本号

python app.py db history


  • 回滚到指定版本

python app.py db downgrade 版本号


  • 注意回滚到之前的版本,再次更新到新的版本,数据可能会丢失,所以尽量避免删除数据,而是去更新数据

邮件扩展


  • 通过Flask_Mail拓展包,可以在Flask程序中发送邮件
  • 原理:Flask-mail连接到简单邮件发送协议(Simple Mail Transfer Protocol,SMTP)服务器 ,并把邮件交给服务器发送

步骤


  • 1 设置邮箱授权码,开启邮箱SMTP服务设置(同django一样)
  • 2 从flask_mail中导入 Mail,Message

from flask_mail import Mail, Message


  • 3 配置邮箱

app.config['MAIL_SERVER'] = "smtp.126.com"
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = "huidongpeng@126.com"
app.config['MAIL_PASSWORD'] = "heima666"
app.config['MAIL_DEFAULT_SENDER'] = 'FlaskAdmin'

  • 4 将app与Mail关联,生成邮箱对象

mail = Mail(app)


  • 5 用Message设置邮件发送内容

msg = Message('这是邮件的主题', recipients=['huidongpeng@126.com'],body='This is flask mail')

- 6 发送邮件

mail.send(msg)


  • 完整代码

#coding:utf-8
from flask import Flask
from flask_mail import Mail, Messageapp = Flask(__name__)# 配置邮件:服务器/端口/安全套接字层/邮箱名/授权码
app.config['MAIL_SERVER'] = "smtp.126.com"
app.config['MAIL_PORT'] = 465
app.config['MAIL_USE_SSL'] = True
app.config['MAIL_USERNAME'] = "huidongpeng@126.com"
app.config['MAIL_PASSWORD'] = "heima666"
app.config['MAIL_DEFAULT_SENDER'] = 'FlaskAdmin'mail = Mail(app)@app.route('/')
def hello_world():return '发送邮件'@app.route('/send_mail')
def send_mail():msg = Message('这是邮件的主题', recipients=['huidongpeng@126.com'],body='This is flask mail')mail.send(msg)return '已发送邮件'if __name__ == '__main__':app.run(debug=True)

蓝图


  • 蓝图(BluePrint)是一个存储操作方法的容器。
  • 这些操作方法在Blueprint被注册到应用之后,就可以被调用。Flask可以通过Blueprint来组织URL以及处理请求

  • 属性:

    • 一个应用可以有多个blueprint
    • 可以将一个blueprint注册到任何一个未使用的url下
    • 在一个应用中,一个模块可以注册多次
    • Blueprint可以拥有自己的模板,静态文件或者其他的通用操作方法,并不是必须要实现应用的视图和函数的
    • 在一个应用初始化时,就应该注册要使用的Blueprint
    • blueprint不是一个完整的应用,它不能独立于应用运行,必须要注册到某个应用中

使用蓝图的步骤


  • 1.创建一个蓝图对象

admin=Blueprint('admin',__name__)


  • 2.在这个蓝图对象上进行操作,注册路由,指定静态文件夹,注册模板过滤器

@admin.route('/')
def admin_home():return 'admin_home'

  • 3.在应用对象上注册这个蓝图对象

app.register_blueprint(admin,url\_prefix='/admin')


单元测试


  • 所谓单元测试,就是用代码测试代码
  • 实际上就是一些‘断言’(assert代码)
  • 为什么要进行单元测试?
    • 好的程序必须能经得起各种测试,测试是软件开发中必须且极为重要的步骤。成型的应用,功能很多。程序人员每编写一段代码,完成一个小功能就应该进行相应的测试工作,这种面向功能单一的小模块进行测试的过程称为单元测试。这是每一个合格的程序人员都要掌握的基本技能。

断言方法


  • 类似一个判断语句
    assert expression 'AssertionError'

if not expression: raise AssertionError

  • 常用的断言方法

assertEqual 如果两个值相等,则pass
assertNotEqual 如果两个值不相等,则pass
assertTrue 判断bool值为True,则pass
assertFalse 判断bool值为False,则pass
assertIsNone 不存在,则pass
assertIsNotNone 存在,则pass

单元测试步骤


  • 1 定义一个类,继承自uniyyest.TestCase

import unittest
class TestClass(unitest.TestCase):pass

  • 2 在测试类中,定义两个固定写法的测试方法

import unittest
class TestClass(unittest.TestCase):#该方法会首先执行,方法名为固定写法def setUp(self):pass#该方法会在测试代码执行完后执行,方法名为固定写法def tearDown(self):pass

  • 3 在测试类中,编写测试代码

import unittest
class TestClass(unittest.TestCase):#该方法会首先执行,相当于做测试前的准备工作def setUp(self):pass#该方法会在测试代码执行完后执行,相当于做测试后的扫尾工作def tearDown(self):pass#测试代码def test_app_exists(self):pass

RESTful


  • REST:具象状态传输。一般解释为“表现层状态转换”
  • RETT是设计风格而不是标准。是指客户端和服务器的交互形式。我们需要关注的重点是如何设计REST风格的网络接口。

如何设计符合RESTful风格的API


  • 1.域名
    将api部署在专用域名下:

http://api.example.com

或者将api放在主域名下:

http://www.example.com/api/


  • 2.版本
    将API的版本号放在url中:

http://www.example.com/app/1.0/info
http://www.example.com/app/1.2/info

  • 3.路径
    路径表示API的具体网址。每个网址代表一种资源。 资源作为网址,网址中不能有动词只能有名词,一般名词要与数据库的表名对应。而且名词要使用复数。

错误示例:

http://www.example.com/getGoods
http://www.example.com/listOrders

正确示例:

#获取单个商品http://www.example.com/app/goods/1
#获取所有商品http://www.example.com/app/goods

  • 4.使用标准的HTTP方法

对于资源的具体操作类型,由HTTP动词表示。 常用的HTTP动词有四个。

GET SELECT :从服务器获取资源。
POST CREATE :在服务器新建资源。
PUT UPDATE :在服务器更新资源。
DELETE DELETE :从服务器删除资源。

示例

#获取指定商品的信息GET http://www.example.com/goods/ID#新建商品的信息POST http://www.example.com/goods#更新指定商品的信息PUT http://www.example.com/goods/ID#删除指定商品的信息DELETE http://www.example.com/goods/ID

  • 5.过滤信息
    如果资源数据较多,服务器不能将所有数据一次全部返回给客户端。API应该提供参数,过滤返回结果。 实例:

#指定返回数据的数量http://www.example.com/goods?limit=10
#指定返回数据的开始位置http://www.example.com/goods?offset=10
#指定第几页,以及每页数据的数量http://www.example.com/goods?page=2&per_page=20

  • 6.状态码
    服务器向用户返回的状态码和提示信息,常用的有

0 OK :服务器成功返回用户请求的数据
201 CREATED :用户新建或修改数据成功。
202 Accepted:表示请求已进入后台排队。
400 INVALID REQUEST :用户发出的请求有错误。
401 Unauthorized :用户没有权限。
403 Forbidden :访问被禁止。
404 NOT FOUND :请求针对的是不存在的记录。
406 Not Acceptable :用户请求的的格式不正确。
500 INTERNAL SERVER ERROR :服务器发生错误

  • 7.错误信息
    一般来说,服务器返回的错误信息,以键值对的形式返回。

{error: 'Invalid API KEY'
}

  • 8.响应结果
    针对不同结果,服务器向客户端返回的结果应符合以下规范。

#返回商品列表GET http://www.example.com/goods#返回单个商品GET http://www.example.com/goods/cup#返回新生成的商品POST http://www.example.com/goods#返回一个空文档DELETE http://www.example.com/goods

  • 9 使用链接关联相关的资源
    在返回响应结果时提供链接其他API的方法,使客户端很方便的获取相关联的信息。

  • 10 其他
    服务器返回的数据格式,应该尽量使用JSON,避免使用XML。


推荐阅读
  • Python 工具推荐 | PyHubWeekly 第二十一期:提升命令行体验的五大工具
    本期 PyHubWeekly 为大家精选了 GitHub 上五个优秀的 Python 工具,涵盖金融数据可视化、终端美化、国际化支持、图像增强和远程 Shell 环境配置。欢迎关注并参与项目。 ... [详细]
  • 本文详细介绍了 Python 中的条件语句和循环结构。主要内容包括:1. 分支语句(if...elif...else);2. 循环语句(for, while 及嵌套循环);3. 控制循环的语句(break, continue, else)。通过具体示例,帮助读者更好地理解和应用这些语句。 ... [详细]
  • 本文探讨了2019年前端技术的发展趋势,包括工具化、配置化和泛前端化等方面,并提供了详细的学习路线和职业规划建议。 ... [详细]
  • 本文将探讨2015年RCTF竞赛中的一道PWN题目——shaxian,重点分析其利用Fastbin和堆溢出的技巧。通过详细解析代码流程和漏洞利用过程,帮助读者理解此类题目的破解方法。 ... [详细]
  • 离线安装Grafana Cloudera Manager插件并监控CDH集群
    本文详细介绍如何离线安装Cloudera Manager (CM) 插件,并通过Grafana监控CDH集群的健康状况和资源使用情况。该插件利用CM提供的API接口进行数据获取和展示。 ... [详细]
  • 在寻找轻量级Ruby Web框架的过程中,您可能会遇到Sinatra和Ramaze。两者都以简洁、轻便著称,但它们之间存在一些关键区别。本文将探讨这些差异,并提供详细的分析,帮助您做出最佳选择。 ... [详细]
  • 深入浅出TensorFlow数据读写机制
    本文详细介绍TensorFlow中的数据读写操作,包括TFRecord文件的创建与读取,以及数据集(dataset)的相关概念和使用方法。 ... [详细]
  • 深入解析:OpenShift Origin环境下的Kubernetes Spark Operator
    本文探讨了如何在OpenShift Origin平台上利用Kubernetes Spark Operator来管理和部署Apache Spark集群与应用。作为Radanalytics.io项目的一部分,这一开源工具为大数据处理提供了强大的支持。 ... [详细]
  • 在Win10上利用VS2015构建Caffe2环境
    本文详细介绍如何在Windows 10操作系统上通过Visual Studio 2015编译Caffe2深度学习框架的过程。包括必要的软件安装、环境配置以及常见问题的解决方法。 ... [详细]
  • 本文探讨了在渗透测试中信息收集阶段使用的几种端口扫描技术,包括nmap、masscan、socket、telnet及nc等工具的应用与比较。 ... [详细]
  • PHP-Casbin v3.20.0 已经发布,这是一个使用 PHP 语言开发的轻量级开源访问控制框架,支持多种访问控制模型,包括 ACL、RBAC 和 ABAC。新版本在性能上有了显著的提升。 ... [详细]
  • 解决Spring Boot项目创建失败的问题
    在尝试创建新的Spring Boot项目时遇到了一些问题,具体表现为在项目创建过程中的两个关键步骤出现错误。本文将详细探讨这些问题及其解决方案。 ... [详细]
  • CentOS 7.6环境下Prometheus与Grafana的集成部署指南
    本文旨在提供一套详细的步骤,指导读者如何在CentOS 7.6操作系统上成功安装和配置Prometheus 2.17.1及Grafana 6.7.2-1,实现高效的数据监控与可视化。 ... [详细]
  • BreederDAO 一周年:回顾历程,庆祝成就,展望未来
    10月标志着BreederDAO踏入Web3.0领域的起点,开启了元宇宙工厂的建设。自成立以来,BreederDAO始终致力于构建多样化的数字资产工厂。 ... [详细]
  • 本文将指导如何向ReactJS计算器应用添加必要的功能,使其能够响应用户操作并正确计算数学表达式。 ... [详细]
author-avatar
loassde_392
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有