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)
whereorder
is'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
rulez
based 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)
whereorder
is'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_by
need 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