Type System
MorpFW CRUD & object management revolves around the idea of resource type. A resource type represents a data model and its respective fields. Resource type definition consist of a Schema, a Collection and a Model class. Collection is very similar to the concept of database table, and model is very similar to a row. Model have a Schema which defines the columns available in the Model.
When designing your application, it helps to think and model your application around the concept of resource type model and collections because views are attached to them.
Schema
Resource type schema in MorpFW is defined through new python 3.7 dataclass library.
Schema in MorpFW is used for:
data validation of JSON data on create/update REST API
data validation on dictionary that is used to create a new instance of resource.
generating JSON schema for publishing in REST API
When defining a schema, it is good that you inherit from morpfw.Schema
as it defines the core metadata required for correct function of the framework.
import morpfw
import typing
from dataclasses import dataclass
@dataclass
class MySchema(morpfw.Schema):
field1: typing.Optional[str] = None
field2: typing.Optional[str] = 'hello world'
Due to the nature of dataclass inheritance,
your field definition must include default values, and if it does not have any,
you should define the field with typing.Optional data type with a default
value of None
Model
Model is the object that is published on a MorpFW path. MorpFW base model class provides the necessary API for model manipulation such as update, delete, save and other model manipulation capabilities of MorpFW.
- class morpfw.interfaces.IModel(request: Request, collection: ICollection, data: dict)
Model is a representation of a data object. It provide a common set of API which is then delegated down to the storage provider.
Model is subscriptable and you can use it like a dictionary to access stored data.
- Parameters:
request – the request object
storage – storage provider
data – initial data on this model
- after_blobput(field: str, blob: IBlob) None
Triggered after BLOB is stored
- after_created() None
Triggered after resource have been created
- after_updated() None
Triggered after resource have been created
- before_blobdelete(field: str) None
Triggered before BLOB is deleted
If the return value is False-ish, delete will be prevented
- before_blobput(field: str, fileobj: BinaryIO, filename: str, mimetype: Optional[str] = None, size: Optional[int] = None, encoding: Optional[str] = None) None
Triggered before BLOB is stored
- before_delete() bool
Triggered before deleting resource
If the return value is False-ish, delete will be prevented
- before_update(newdata: dict) None
Triggered before updating resource with new values
- abstract delete()
Delete model
- abstract delete_blob(field: str)
Delete blob
- abstract get_blob(field: str) IBlob
Return blob
- abstract json() dict
Convert model to JSON-safe dictionary
- abstract links() list
Generate links for this model
- abstract put_blob(field: str, fileobj: BinaryIO, filename: str, mimetype: Optional[str] = None, size: Optional[int] = None, encoding: Optional[str] = None) IBlob
Receive and store blob object
- abstract rulesprovider()
Return pluggable business rule adapter for this model
- abstract save()
Persist model data into backend storage
- abstract set_initial_state()
Initialize default statemachine state for this model
- abstract statemachine()
Return PyTransition statemachine adapter for this model
- abstract update(newdata: dict, secure: bool)
Update model with new data
- abstract xattrprovider()
Return extended attributes provider for this model
- blob_fields: List[str]
List of blob field names allowed on this model
- blobstorage_field: str
Field name on the model data which will be storing blob references
- data: IDataProvider
Data provider
- delete_view_enabled: bool
When set to True, will enable DELETE view to delete model
List of fields that should be hidden from output
- identifier: str
url identifier for this model
- linkable: bool
Set whether object is linkable or not. If an object is linkable, its json result will have links attribute
- abstract property schema: Type[ISchema]
The dataclass schema which this model will be using
- update_view_enabled: bool
When set to True, will enable PATCH view to update model
- uuid: str
uuid of this model
Collection
Collection is the container for Model objects. Collection manages the single type of Model and and provide collection level Model object management API such as create, search and aggregate.
- class morpfw.interfaces.ICollection
Collection provide an API for querying group of model from its storage
- abstract aggregate(query: Optional[dict] = None, group: Optional[dict] = None, order_by: Optional[tuple] = None) List[IModel]
Get aggregated results
: param query: Rulez based query : param group: Grouping structure : param order_by: Tuple of
(field, order)whereorderis'asc'or'desc': todo: Grouping structure need to be documented
- before_create(data: dict) None
Triggered before the creation of resource
- abstract json() dict
JSON-safe dictionary representing this collection
- abstract links() list
Links related to this collection
- abstract search(query: Optional[dict] = None, offset: int = 0, limit: Optional[int] = None, order_by: Optional[tuple] = None, secure: bool = False) List[IModel]
Search for models
Filtering is done through
rulezbased JSON/dict query, which defines boolean statements in JSON/dict structure.: param query: Rulez based query : param offset: Result offset : param limit: Maximum number of result : param order_by: Tuple of
(field, order)whereorderis'asc'or'desc'- : param secure: When set to True, this will filter out any object which
current logged in user is not allowed to see
: todo:
order_byneed to allow multiple field ordering
Storage
Model and collection gets their data from a storage provider. It abstracts the interface to storage backends, allowing custom storage backends to be implemented.
- class morpfw.interfaces.IStorage(request: Request, blobstorage: Optional[IBlobStorage] = None)
Aggregateable storage
- abstract aggregate(query: Optional[dict] = None, group: Optional[dict] = None, order_by: Union[None, list, tuple] = None) list
return aggregation result based on specified rulez query and group
- abstract delete(identifier, model)
delete model data
- abstract search(query: Optional[dict] = None, offset: Optional[int] = None, limit: Optional[int] = None, order_by: Union[None, list, tuple] = None) Sequence[IModel]
return search result based on specified rulez query
- abstract update(identifier, data)
update model with values from data
BlobStorage
Storage provider may have a BLOB storage backend implemented which will handle the management of BLOBs
- class morpfw.interfaces.IBlobStorage
- abstract delete(uuid: str)
Delete blob data
- abstract get(uuid: str) Optional[IBlob]
Return blob data
- abstract put(field: str, fileobj: BinaryIO, filename: str, mimetype: Optional[str] = None, size: Optional[int] = None, encoding: Optional[str] = None, uuid: Optional[str] = None) IBlob
Receive and store blob data