- A (slightly magical) dependency to automatically add CRUD RPC entrypoints to nameko microservices.
- Based on Sqlalchemy models.
- The aim is to reduce the amount of code required to implement common methods.
- Uses sqlalchemy-filters.
- Works in conjunction with sqlalchemy dependency providers such as nameko-sqlalchemy.
- Each dependency also can be used in other methods to get/manipulate model instances.
- Customisable components.
Install from PyPI:
pip install nameko-autocrud
from nameko_sqlalchemy import DatabaseSession
from nameko_autocrud import AutoCrud
class MyService:
name = 'my_service'
session = DatabaseSession(models.Base)
member_auto_crud = AutoCrud(
session,
model_cls=models.Member,
get_method_name='get_member',
list_method_name='list_members',
page_method_name='page_members',
count_method_name='count_members',
create_method_name='create_member',
update_method_name='update_member',
delete_method_name='delete_member',
)
payment_auto_crud = AutoCrud(
session,
model_cls=models.Payment,
get_method_name='get_payment',
list_method_name='list_payments'
)
@rpc
def my_entrypoint(self, value):
return value + 1
This will automatically make the following additional RPC entrypoints available:
get_member(self, id_)
list_members(self, filters=None, offset=None, limit=None, order_by=None)
page_members(self, page_size, page_num, filters=None, order_by=None)
count_members(self, filters=None)
update_member(self, id_, data)
create_member(self, data)
delete_member(self, id_)
get_payment(self, id_)
list_payments(self, filters=None, offset=None, limit=None, order_by=None)
The dependencies themselves can be used to manipulate sqlalchemy objects within other code E.g.
@rpc
def copy_member_name(self, from_id, to_id):
member = self.member_auto_crud.get(from_id)
self.member_auto_crud.update(to_id, {'name': member.name})
The *_method_name
kwargs are used to declare the name of each crud method. Setting this value to None (or not providing the kwarg) will prevent the method from being generated.
cake_crud = AutoCrud(
session, model_cls=models.Cake,
delete_method_name='eat_cake',
update_method_name=None,
)
TODO - marshmallow examples
By default each generated service rpc method is decorated with the standard nameko.rpc.rpc
decorator.
This can be overridden for all methods by supplying the rpc
kwarg to AutoCrud
. For example, if the service is making use of nameko-amqp-retry, then AutoCrud
should be instantiated with rpc=nameko_amqp_retry.rpc
.
The rpc decorator can be overridden for specific methods by supplying kwargs like get_rpc
, list_rpc
etc.
This makes it possible to declare the expected_exceptions
or sensitive_variables
that may be required for a particular method. E.g.
from nameko.rpc import rpc
from nameko_sqlalchemy import DatabaseSession
from nameko_autocrud import AutoCrud, NotFound
class MyService:
name = 'my_service'
session = DatabaseSession(models.Base)
cake_crud = AutoCrud(
session, model_cls=models.Cake,
get_method_name="get_cake",
list_method_name="list_cakes",
get_rpc=rpc(expected_exceptions=NotFound),
)
Nameko-autocrud includes an additional AutoCrudWithEvents
DependencyProvider. This has the same behaviour as AutoCrud
but can dispatch nameko events for create
, update
& delete
actions.
from nameko.events import EventDispatcher
from nameko_sqlalchemy import DatabaseSession
from nameko_autocrud import AutoCrudWithEvents
class MyService:
name = 'my_service'
session = DatabaseSession(models.Base)
dispatcher = EventDispatcher()
payment_auto_crud = AutoCrudWithEvents(
session, dispatcher, 'payment',
model_cls=models.Payment,
create_event_name='payment_created',
update_event_name='payment_updated',
delete_event_name='payment_deleted',
create_method_name='create_payment',
update_method_name='update_payment',
delete_method_name='delete_payment',
)
Nameko events will be generated for every *_even_name
parameter given. If the parameter is set to None
or not present, the event will not be dispatched.
Create events will be dispatched after a successful creation. The event-name is given by create_event_name
and the payload will be of the form:
{
'payment': {<serialized payment instance after creation>}
}
Where the payment
key is given by the required event_entity_name
parameter.
Update events will be dispatched after a successful update that resulted in changes. The event-name is given by update_event_name
and the payload will be of the form:
{
'payment': {<serialized payment instance after the update>},
'changed': [<list of the changed fields>],
'before': {<serialized payment instance before the update>},
}
Where the payment
key is given by the required event_entity_name
parameter.
Delete events will be dispatched after a successful deletion. The event-name is given by delete_event_name
and the payload will be of the form:
{
'payment': {<serialized payment instance before deletion>}
}
Where the payment
key is given by the required event_entity_name
parameter.
TODO - Specifying event serializer