# 3.8 定义第一个模型类以及反向生成

新建一个模块model，用于存储数据库表对应的业务模型，在编写model层的模型时，一定要忘记数据库表，重点要放在业务模型的抽象中来

* sqlalchemy 是一个类库，用于根据定义的model反向生成数据库表
* Flask\_SqlAlchemy 是Flask在sqlalchemy基础上封装的一个组件。提供了更加人性化的API来操作数据库
*   pipenv 按照 `pipenv install flask-sqlalchemy`

    ![image.png](https://upload-images.jianshu.io/upload_images/7220971-fefc63c1fbbe994d.png?imageMogr2/auto-orient/strip|imageView2/2/w/1240)

## 1.编写模型类

```python
from sqlalchemy import Column,Integer,String


class Book():
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=True)
    author = Column(String(30), default="未名")
    binding = Column(String(20))
    publisher = Column(String(50))
    price = Column(String(20))
    pages = Column(Integer)
    isbn = Column(String(15), nullable=True, unique=True)
    summary = Column(String(1000))
    image = Column(String(50))
```

## 2.将模型映射到数据库中

### 1.在模型类中引入Flask\_SqlAlchemy，并做相关声明

app/models/book.py

```python
from sqlalchemy import Column, Integer, String
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

# 继承db.Model
class Book(db.Model):
    id = Column(Integer, primary_key=True, autoincrement=True)
    title = Column(String(50), nullable=True)
    author = Column(String(30), default="未名")
    binding = Column(String(20))
    publisher = Column(String(50))
    price = Column(String(20))
    pages = Column(Integer)
    isbn = Column(String(15), nullable=True, unique=True)
    summary = Column(String(1000))
    image = Column(String(50))
```

### 2.在app中插入Flask\_SqlAlchemy对象

app/\_\_init\_\_.py

```
def create_app():
    app = Flask(__name__)
    app.config.from_object("app.secure")
    app.config.from_object("app.settings")
    register_blueprint(app)

    # 将db插入app
    db.init_app(app)
    # 创建所有的表
    db.create_all()
    return app
```

### 3.书写配置文件

app/secure.py

```python
...
...
# key-SQLALCHEMY_DATABASE_URI不能随意修改
# URI规则:数据库类型+驱动://账号:密码@host:port/dbname
SQLALCHEMY_DATABASE_URI = "mysql+cymysql://root:root@localhost:3306/fisher"
...
...
```

cysql驱动需要安装

```
pipenv install cymysql
```

上面的操作完成以后启动项目，会报如下错误

```
/Users/gaowenfeng/.local/share/virtualenvs/fisher-4xlkyzha/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py:794: FSADeprecationWarning: SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and will be disabled by default in the future.  Set it to True or False to suppress this warning.
  'SQLALCHEMY_TRACK_MODIFICATIONS adds significant overhead and '
Traceback (most recent call last):
  File "/Users/gaowenfeng/project/pycharm/fisher/fisher/fisher.py", line 10, in <module>
    app = create_app()
  File "/Users/gaowenfeng/project/pycharm/fisher/fisher/app/__init__.py", line 14, in create_app
    db.create_all()
  File "/Users/gaowenfeng/.local/share/virtualenvs/fisher-4xlkyzha/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 963, in create_all
    self._execute_for_all_tables(app, bind, 'create_all')
  File "/Users/gaowenfeng/.local/share/virtualenvs/fisher-4xlkyzha/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 940, in _execute_for_all_tables
    app = self.get_app(app)
  File "/Users/gaowenfeng/.local/share/virtualenvs/fisher-4xlkyzha/lib/python3.6/site-packages/flask_sqlalchemy/__init__.py", line 912, in get_app
    'No application found. Either work inside a view function or push'
RuntimeError: No application found. Either work inside a view function or push an application context. See http://flask-sqlalchemy.pocoo.org/contexts/.

Process finished with exit code 1
```

这是因为在Flask中，不是实例化了app核心对象，其他的代码就可以直接用到。所以在上面第二部`create_all()`方法中，应该将app传入

```
db.create_all(app=app)
```

通过以上修改后，数据库中成功生成了数据库表
