# 数据层 数据层是资源管理器和数据交互的CRUD接口。它能以非常灵活的方式使用任何ORM或数据储存。我们甚至还能创建基于多个ORM和数据储存的数据层,以此来管理我们的对象。数据层针对对象和关系实现了CRUD接口,同时管理着分页、过滤和排序功能。 Flask-REST-JSONAPI基于知名的ORM [SQLAlchemy](https://www.sqlalchemy.org/)框架已经实现了一个全功能的数据层。 > **注:** > > 资源管理器默认的数据层使用的是SQLAlchemy。所以,如果我们要使用它,不必在资源管理器中明确声明。 为了配置数据层,我们必须在资源管理器中设置一些必要参数。 例: ```python from flask_rest_jsonapi import ResourceList from your_project.schemas import PersonSchema from your_project.models import Person class PersonList(ResourceList): schema = PersonSchema data_layer = {'session': db.session, 'model': Person} ``` 我们也能在资源管理中,给数据层,嵌入额外的方法。这里有两种额外的方法: - query(查询方法):“query”方法使用view_kwargs作为参数,并返回替代的查询结果。使用ResourceList资源管理器的GET方法时,会调用query,获取对象集合。 - pre / post process(前置后置方法):所有CRUD和关系操作都有一对前置/后置处理方法。因此,我们能在数据层的每次操作前和后,添加额外的处理。每个前置/后置方法中,使用的具体参数可以参考基类[flask_rest_jsonapi.data_layers.base.Base](https://github.com/miLibris/flask-rest-jsonapi/blob/master/flask_rest_jsonapi/data_layers/base.py)。 例: ```python from sqlalchemy.orm.exc import NoResultFound from flask_rest_jsonapi import ResourceList from flask_rest_jsonapi.exceptions import ObjectNotFound from your_project.models import Computer, Person class ComputerList(ResourceList): def query(self, view_kwargs): query_ = self.session.query(Computer) if view_kwargs.get('id') is not None: try: self.session.query(Person).filter_by(id=view_kwargs['id']).one() except NoResultFound: raise ObjectNotFound({'parameter': 'id'}, "Person: {} not found".format(view_kwargs['id'])) else: query_ = query_.join(Person).filter(Person.id == view_kwargs['id']) return query_ def before_create_object(self, data, view_kwargs): if view_kwargs.get('id') is not None: person = self.session.query(Person).filter_by(id=view_kwargs['id']).one() data['person_id'] = person.id schema = ComputerSchema data_layer = {'session': db.session, 'model': Computer, 'methods': {'query': query, 'before_create_object': before_create_object}} ``` > **注:** > > 数据层方法可以不必在资源管理器中声明。我们能在专用的模块或模型中声明它。 例: ```python from sqlalchemy.orm.exc import NoResultFound from flask_rest_jsonapi import ResourceList from flask_rest_jsonapi.exceptions import ObjectNotFound from your_project.models import Computer, Person from your_project.additional_methods.computer import before_create_object class ComputerList(ResourceList): schema = ComputerSchema data_layer = {'session': db.session, 'model': Computer, 'methods': {'query': Computer.query, 'before_create_object': before_create_object}} ``` ## SQLAlchemy --- 必要参数: - **session**:数据层使用的session连接 - **model**:数据层使用的ORM模型 可选参数: - **id_field**:自定义识别列,用于替代模型的主键 - **url_field**:自定义路由中的参数名,用于替代默认的参数名id 默认情况下,当我们使用inlcude参数查询时,SQLAlchemy会懒加载关联的数据。如果我们想停用这个特性,我们可以将数据层的eagerload_includes设置为False。 ## 定制数据层 --- 之前提到过,我们也能创建使用我们自己的数据层。定制的数据层必须继承自基类[flask_rest_jsonapi.data_layers.base.Base](https://github.com/miLibris/flask-rest-jsonapi/blob/master/flask_rest_jsonapi/data_layers/base.py)。通过这个基类,我们能看到在数据层中,所有可以定制的内容。 用例: ```python from flask_rest_jsonapi import ResourceList from your_project.schemas import PersonSchema from your_project.data_layers import MyCustomDataLayer class PersonList(ResourceList): schema = PersonSchema data_layer = {'class': MyCustomDataLayer, 'param_1': value_1, 'param_2': value_2} ``` > **注:** > > 在资源管理器的data_layer字典中,除了“class”的所有参数,都会作为数据层实例的属性。这样,便于数据层内部进行调用。