I am using the Django Rest Framework to present a RESTful API. I have a router/viewset/serializer creating an endpoint for a Person
resource:
/api/People/<id>/
I would would like some way of triggering a non-idempotent action on this resource (for example send-email-to
). One idea I had to do so without having to re-do a lot of the routing/serialization infrastructure was to add a write-only boolean field to the serializer:
class PersonSerializer(serializers.ModelSerializer):
send_email = serializers.BooleanField(write_only=True, required=False)
and then add a write-only property to the model:
class Person(models.Model):
...
def do_send_email(self, value):
# We also need to check the object is fully constructed here, I think
if do_send_email:
...
send_email = property(fset=do_send_email)
and then I can PATCH
to the end point with the payload of send_email=True
.
Is this the best way to accomplish an RPC like function using a REST API? Is this the best way to accomplish this in DRF? Ideally I would like to solve this problem having to-implement as little as possible (ie see how few lines of code the solution is). send-email-to
is not the only action that I would like to handle.
You can use the extra actions drf provides. In your case especifically, I would use @detail_route.
Something like that:
@detail_route(methods=['post'])
def send_mail(self, request, pk=None):
send_mail_to(pk) # Write here your email function.
You have to define this function within the Person viewset so, in order to call this function, you will have to POST at /people/{person_id}/send_mail where {person_id} is the primary key for the person.
As a side note, since this function are synchronously called from the client and it may take a while to answer, I would recommend you the use of celery. This will allow you to call the send_mail_to function asynchronously without delaying the user response.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With