Assist creation of Pumpwood views in Flask.
pumpwood-flaskviews .
Pumpwood is a native brasilian tree
which has a symbiotic relation with ants (Murabei)
This package assist the creation of views in flask using Pumpwood pattern.
Expose models functions at the API. It is possible to expose normal and classmethods, the first argument for each one should respect the convention self and cls respectively.
from pumpwoodflask_views.action import action
class Person(db.Model):
"""Citizen of a far far way country."""
name = db.Column(db.String(3), nullable=True, doc=(
"csv field delimiter when using file input"))
birth_date = db.DateTime(db.String(3), nullable=True, doc=(
"csv decimal delimiter when using file input"))
__tablename__ = 'person'
@action(info='Marry person to another.')
def marry(self, person_id: int, contract: str = None) -> bool:
"""
Marry person to another one.
Args
----
person_id: int
Id of the person to whom the object should be married.
Kwargs
----------
contract: str
Set the legal contract used.
Returns
-------
bool
Returns true if it was possible to process the action.
"""
...
return True
@classmethod
@action(info='Send cards to today's birthday.')
def process_birthday_cards(cls, reference_date: datetime.datetime) -> int:
"""
Send birthday cards to every one with birthday today. If reference_date
if reference_date is passed it will be used instead of today as
reference.
Args
----
No args.
Kwargs
----------
reference_date: datetime.datetime
Reference date to check for birthdays.
Returns
-------
int
Number of birthday cards sent.
"""
...
return True
from pumpwood_communication.microservices import PumpWoodMicroService
microservice = PumpWoodMicroService(
server_url="http://0.0.0.0:8080/",
username="pumpwood", password="pumpwood")
microservice.login()
# List the actions avaiable for the model Person, it will include information
# about the parameters and also the doc string associated with the function.
person_actions = microservice.list_actions(model_class="Person")
# Return the serialized person object, the parameters used at the action and
# the result
results = microservice.excute_action(
model_class="Person", pk=3, action="marry",
parameters={"person_id": 1})
# process_birthday_cards is a classfunction so it is not associated with an
# object
microservice.excute_action(
model_class="Person", action="process_birthday_cards")
Integrate pumpwood authentication with flask end-points. After setting the Auth host it is possible o call check_authorization, it will pass request headers to auth end-point and check if user is authenticated.
AuthFactory.set_server_url(server_url=config_dict['AUTH_SERVER'])
def flask_end_point():
AuthFactory.check_authorization()
return ...
Extend SQLAlchemy fields for some common used fields in Pumpwood.
- GeometryField: Serialize shapely geometry fields.
- ChoiceField: Serialize sqlalchemy_utils ChoiceType fields.
Define a base serializer for pumpwood models which always return at least pk and model_class.
Define pumpwood basic views. They have always the same pattern:
Description of the model, this can be used to display model navegation on side bar. During call to end-point information this attribute will be passed to i8s for translation.
Dictionary of tag/value, this will be registred at model class route.
String setting icon name to be display at the frontend.
Connection to database.
Model class of Flask SQLAlchemy.
Storage object to connect to S3, blog, GCP storage, etc...
Microservice used to connect to other microservices in pumpwood. This microservice must be authenticated.
Serialize to be used to serialize model objects at end-points.
List of fields that will be considered as default to be displayed when calling list with default fields.
It is possible to modify function get_list_fields
to make
list_fields to adapt to request.
A dictionary to describe relation of this model with other models in Pumpwood. This is informational data and does nos verify if model actualy exists on Pumpwood. There are two types of
Set a dictionary for rendering frontend, it specify groups of fields to be displayed together. It also permits pass to front the ordering of the fields. Dictionary structure:
# List of the field sets that will be passed to front-end
# permitting setting them in an order
gui_retrieve_fieldset = [
{
# Name of the field set
"name": "Main",
# Fields that will be returned on this field set,
# with permits ordering the fields on front end.
"fields": ['name', 'birth_date']
}, {
# It can be passed many relations such as children_set
"name": "Relations",
"fields": ['married_to_id', 'children_set']
}, {
"name": "Jobs",
"fields": ['job_set']
}
]
It is possible to modify function get_gui_retrieve_fieldset
to make list_fields to adapt to request.
Permit pass to front end how this object should be displayed on retrieve view. It is set to substitute using data from the model, example:
# This will help front end to display title of retrieve page
# as '5 | Jonh Doe' substituting values os pk and name.
gui_verbose_field = '{pk} | {name}'
It is possible to modify function get_gui_verbose_field
to make list_fields to adapt to request.
Set a list of fields that will be considered as read-only on front-end, but can be modified using API. This is useful since some data might be only modified thought API such as jobs start and end time.
# This will set birth_date as read-only on field description,
# although it is still possible to modify it using the API
gui_readonly = ["birth_date"]
It is possible to modify function get_gui_readonly
to make list_fields to adapt to request.
- list (/rest/[model_class]/list/): List objects using query parameters passed as dictionary payload, paginate by 50.
- list_without_pag (/rest/[model_class]/list-without-pag/): Same as list, but return all objects.
- list_one (/rest/[model_class]/list-one/): List one object using list serialize (fewer fields).
- retrieve (/rest/[model_class]/retrieve/[pk]): Return all information from one object.
- object_template (/rest/[model_class]/retrieve/): Return an empty object template.
- retrieve_file (/rest/[model_class]/retrieve-file/[pk]?file-field=[field]): retrieve file which path is saved on file-field argument.
- remove_file_field (/rest/[model_class]/remove-file-field/[pk]?file-field=[field]): delete file which path is saved on file-field argument using streaming.
- retrieve_file_streaming (/rest/[model_class]/retrieve-file-streaming/[pk]?file-field=[field]): retrieve file which path is saved on file-field argument using streaming.
- save_file_streaming (/rest/[model_class]/save-file-streaming/[pk]?file-field=[field]): Save a file in file-field using streaming.
- save (/rest/[model_class]/save/) Save file object passed in payload.
- delete (/rest/[model_class]/delete/[pk]): Remove an object from database.
- delete_many (/rest/[model_class]/delete/): Delete many objects using query dictionary.
- list_actions (/rest/[model_class]/actions/): List actions available for model_class.
- execute_action (/rest/[model_class]/actions/[action name]/[pk]): Run action over object pk.
- search_options (/rest/[model_class]/options/): Retrieve information for list fields and filters.
- fill_options (/rest/[model_class]/options/): Pass an incomplete object as post payload and receives the validation of the fields and update the choice possibilities.
PumpWoodDataFlaskView
- Same as PumpWoodFlaskView...
- pivot (/rest/[model_class]/pivot/): Retrieve data using query dict, but instead of using serializers use pandas data frame and parse result with to_dict. It is possible to pivot data using the columns.
- bulk_save (/rest/[model_class]/bulk-save/): Bulck save data on database.
PumpWoodDimentionsFlaskView
- Same as PumpWoodFlaskView...
- list_dimentions (/rest/[model_class]/list-dimentions/): List avaiable dimentions in objects resulting from the query.
- list_dimention_values (/rest/[model_class]/list-dimention-values/): List values associated with dimentions in objects resulting from the query.
Example for defining a PumpWoodFlaskView:
from pumpwoodflask_views.views import PumpWoodFlaskView
from models import Person
from serializers import PersonSerializer
from singletons import storage_object, microservice
class PersonView(PumpWoodFlaskView):
description = "Person"
# Used when registering end-point on routes
dimentions = {
"service": "test-service",
"type": "human",
}
icon = None
db = db
model_class = Person
storage_object = storage_object
microservice = microservice
serializer = PersonSerializer
foreign_keys = {
'married_to_id': {
'model_class': 'Person', 'many': False,
'display_field': 'name'}
'children_set': {
'model_class': 'Children', 'many': True,
'foreign_key': 'parent_id', 'read_only': True},
'job_set': {
'model_class': 'Job', 'many': True,
'foreign_key': 'person_id', 'read_only': False},
}
#######
# Gui #
list_fields = [
'pk', 'model_class', 'name', 'birthday', 'married_to_id']
gui_retrieve_fieldset = [
{
"name": "Main",
"fields": ['name', 'birth_date']
}, {
"name": "Relations",
"fields": ['married_to_id', 'children_set']
}, {
"name": "Jobs",
"fields": ['job_set']
}
]
gui_verbose_field = '{pk} | {name}'
gui_readonly = ["birth_date"]
#######