flask的基本操作
lask
django是大而全,提供所有常用的功能
flask是小而精,只提供核心功能
环境配置
为了防止 django和 flask环境相互冲突,可以使用 虚拟环境分割开
pip install virtualenv virtualenvwrapper-win # 安装虚拟环境基本的依赖包
mkvirtualenv flask # 创建一个叫 flask的虚拟环境
deactivate # 退出当前虚拟环境
rmvirtualenv flask # 删除名叫 flask的虚拟环境
workon flask # 进入虚拟环境flask
pip install -r requirements.txt # 在虚拟环境中安装flask必备的包
基本流程
配置项可以参考 官方 文档
-
创建
flaskAPP -
定义视图函数
-
对视图函数配置路由
-
使用装饰器,配置路由
-
调用app的方法
add_url_rule对视图函数配置路由
-
-
直接运行APP
from flask import Flask
# __name__ 当前 文件的名字
# __file__ 当前 文件的路径
# 1. 创建flask的app
app = Flask(__name__)
# 2.1 创建视图函数,利用装饰器可以配置路由
项目配置
配置文件
通过专门的配置文件,读取配置项,适用于配置项较多
settings.py
class Config(object):
DEBUG = True
主模块
import os
from flask import Flask
from settings import Config
app = Flask(__name__)
# app.config.from_object('settings.Config')
app.config.from_object(Config)
工厂模式
如果在一个函数中 创建对象,那么就可以创建多个实例。
那么这样做有什么用呢?
-
用于测试。可以针对不同的情况使用不同的配置来测试应用。
-
用于多实例,如果你需要运行同一个应用的不同版本的话。当然你可以在服务器上 使用不同配置运行多个相同应用,但是如果使用应用工厂,那么你可以只使用一个 应用进程而得到多个应用实例,这样更容易操控。
app/settings.py
class Config(object):
# 配置项在flask文档中已经规定好
DEBUG = True
app/__init__.py
from flask import Flask
from .settings import Config
def create_app():
# 1. 创建app对象
app = Flask(__name__)
# 2. 导入配置类
app.config.from_object(Config)
# 3. 返回 flask对象
return app
主模块
main.py
# 1. 导入工厂函数
from app import create_app
# 2. 生成APP
app = create_app()
小结
想要创建一个flask项目,都需要手动创建
-
创建app包
-
settings.py: 项目 的配置文件 -
__init__.py: 定义工厂函数,生成 flask app
-
-
-
__init__.py: 创建蓝图对象, 负责管理当前模块中的所有代码 -
models.py: 实现 商品模块中的 所有 商品模型类 -
views.py: 实现 商品模块中的所有视图 -
每个蓝图 代码搞定之后,需要在 主app中 注册 app, 类似于 django 的注册 app
-
-
请求参数
视图处理过程中,都是接收请求,处理逻辑,返回响应
flask中
request对象 不是 局部对象,也不属于某个视图函数,而是在 全局中 拥有同一个 请求对象
路径参数
GET student/1/
-
int: 获取整数 -
string: 也是默认类型,得到字符串
# GET student/1/
查询字符串参数
GET student/list/?page=3&size=5&a=3&a=9: 一般是 GET请求时,传递 查询字符串参数
from flask import request
请求体参数-表单数据
POST、PUT可以携带请求体参数, 请求体参数包括: 表单数据、json数据flask视图处理过程中,默认只 支持
GET请求,想要支持其他请求方式,应该指明 请求方式
请求体参数-json
小结
将 查询和添加 放到同一个视图中,判断不同的请求方式,从而执行不同的处理逻辑
项目构造
python包
flask项目,一切功能围绕 核心app 来完成, 这个包就用来构造 核心APP
-
app/settings.py: 项目的配置文件
class Config(object):
DEBUG = True
SQLALCHEMY_DATABASE_URI = 'mysql://root:mysql@localhost:3306/flask'
# mysql://用户名:密码@IP地址:端口号/数据库名
SQLALCHEMY_TRACK_MODIFICATIONS = False
-
app/extensions.py: 项目所使用的第三方扩展插件
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
from flask_cors import CORS
# 环境中,使用 mysqlclient 链接mysql,就可以正常使用
# 如果使用的是pymysql链接 mysql, 就需要加一些配置项
# import pymysql
# pymysql.install_as_MySQLdb()
db = SQLAlchemy()
migrate = Migrate()
cors = CORS()
def config_extensions(app):
db.init_app(app)
migrate.init_app(app, db=db)
cors.init_app(app)
-
app/__init__.py: 定义工厂函数,生成核心flask APP
from flask import Flask
from .settings import Config
from .extensions import config_extensions
def create_app():
# 1. 创建APP
app = Flask(__name__)
# 2. 导入配置参数
app.config.from_object(Config)
# 3. 导入 第三方的插件
config_extensions(app)
# 4. 返回APP
return app
项目的管理文件
在项目中,创建
manage.py
-
manage.py
from flask_script import Manager, Server
from flask_migrate import MigrateCommand
from app import create_app
# 1. 利用工厂函数生成app
app = create_app()
# 2. 创建管理对象,管理项目
manage = Manager(app)
# 3. 构建命令
manage.add_command('runserver', Server(host='0.0.0.0', port=7000))
manage.add_command('db', MigrateCommand)
if __name__ == '__main__':
# 利用管理器启动服务
manage.run()
命令
在项目的终端可以使用如下命令,操作项目
python manage.py runserver # 启动flask 服务
python manage.py db init # 只有第一次迁移时,才会执行 该命令, 执行完,会生成迁移文件
python manage.py db migrate # 生成迁移文件,出路第一次之外,任何修改模型类,都需要 执行该命令, 生成迁移文件
python manage.py db upgrade # 根据迁移文件,生成表
学校子应用
-
school/__init__.py: 创建蓝图对象, 创建完成,需要 注册蓝图
from flask.blueprints import Blueprint
school_bp = Blueprint('school', __name__)
# 为了让蓝图,管理你的 模型类和视图,因此需要导入
from .models import *
from .views import *
-
school/models.py: 创建模型类
from app.extensions import db
# 学生: id、姓名、年龄、性别
class Student(db.Model):
__tablename__ = 'tb_student' # 指定表名
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
name = db.Column(db.String(20))
age = db.Column(db.Integer)
gender = db.Column(db.String(5))
需要在 蓝图,导入模型类,以便项目识别 模型类
生成迁移文件:
python manage.py db migrate生成表:
python manage.py db upgrade
视图
school/views.py: 实现 逻辑处理
from flask import request
from school import school_bp
from .models import Student
from app.extensions import db
from sqlalchemy.exc import SQLAlchemyError
基本操作
from flask_restful import Resource, reqparse, marshal_with
from sqlalchemy.exc import SQLAlchemyError
from .fields import book_page_fields
from .models import *
class BookView(Resource):
def post(self):
parser = reqparse.RequestParser()
parser.add_argument('title', type=str, location=['form', 'json'], required=True, help='图书标题不能缺少')
parser.add_argument('bread', type=int, location=['form', 'json'], default=0, help='输入合法的阅读量')
# 1. 获取参数
title = parser.parse_args().get('title')
bread = parser.parse_args().get('bread')
# 2. 创建图书对象
book = Book(title=title, bread=bread)
# 3. 添加图书对象到事务
db.session.add(book)
# 5. 提交事务
try:
db.session.commit()
except:
return {'msg': '添加失败'}, 500
# 6. 正常返回
return {
'id': book.id,
'title': book.title,
'bread': book.bread
}, 201
详情、修改、删除
class BookDetailView(Resource):
def get(self, pk):
# 1. 通过主键id,查询 图书对象, id对应的数据不存在,得到结果为None
book = Book.query.get(pk)
# 2. 如果book图书不存在
if not book:
return {
'msg': '图书不存在'
}, 404
# 3. 返回对象
return {
'id': book.id,
'title': book.title,
'bread': book.bread
}
def delete(self, pk):
Book.query.filter_by(id=pk).delete()
db.session.commit()
return None, 204
def put(self, pk):
parser = reqparse.RequestParser()
# 1. 根据主键,查询到需要修改的 图书对象
book = Book.query.get(pk)
# 2. 判断该图书 是否 存在
if not book:
return {
'msg': '找不到'
}, 404
# 3. 解析参数,如果没有传递参数,设置 图书的 原属性 为默认值
parser.add_argument('title', type=str, location=['json', 'form'], default=book.title)
parser.add_argument('bread', type=int, location=['json', 'form'], default=book.bread)
# 4. 获取参数,得到字典
args = parser.parse_args()
# 5.将对象的值,赋值为 传递的新值
book.title = args.get('title')
book.bread = args.get('bread')
# 6.修改完成,需要提交事务,让修改生效
db.session.commit()
return {
'msg': '修改成功'
}, 201
小结
模型类.query.filter_by(字段=值), 结果是一个 查询集
模型类.query.get(主键的值), 结果是一个 对象,不存在,结果为None
模型类.query.get_or_404(主键的值), 结果是一个对象, 不存在,抛出 404异常
模型类.query.all(), 结果是查询集
pagination = 模型类.query.paginate(page=xxx, per_page=xxx), 结果是分页器对象
pagination.items: 当前页的数据,是一个查询集
pagination.pages: 总页码
pagination.total: 总的记录数量
Vue
添加数据
<template>
<div>
<!-- 1. 获取表单数据 -->
标题: <input type="text" v-model="title">
阅读量: <input type="text" v-model="bread">
<!-- 2. 对按钮的点击事件,绑定方法 -->
<button @click="postBook">添加</button>
</div>
</template>
<script>
export default {
name: "Book",
data() {
return {
title: '',
bread: 0
}
},
methods: {
postBook() {
// 3. 使用axios发送数据
this.$axios.post('/book', {'title': this.title, 'bread': this.bread})
.then(resp => {
alert('添加成功')
})
.catch(err => {
alert('添加失败')
})
}
}
}
</script>
列表分页展示
<template>
<div>
<!-- 3 循环展示所有图书以及页码 -->
<table>
<tr v-for="b in books">
<td>
修改页面
<template>
<div>
<!-- 4. 将原始数据和表单进行双向绑定 -->
标题:<input type="text" v-model="book.title">
阅读量: <input type="text" v-model="book.bread">
<!-- 5. 对修改按钮,绑定方法 -->
<button @click="updateBook">更新</button>
</div>
</template>
<script>
export default {
name: "BookUpdate",
data() {
return {
id: this.$route.query.id,
book: {
// 1. 从路由对象中获取传递的id
title: '',
bread: ''
}
}
},
methods: {
// 2. 根据id,查询图书的原始数据
getBook() {
this.$axios.get('book/' + this.id)
.then(resp => {
this.book.title = resp.data.title
this.book.bread = resp.data.bread
})
},
// 6. 定义修改方法
updateBook() {
this.$axios.put(`book/${this.id}`, this.book)
.then(resp => {
this.$router.push('/')
})
.catch(err => {
alert('修改失败')
})
}
},
mounted() {
// 3. 挂载请求数据的方法
this.getBook();
}
}
</script>
浙公网安备 33010602011771号