使用DRF在RESTful API中实现RPC

Ale*_*erg 3 django rest django-rest-framework

我正在使用Django Rest Framework来呈现RESTful API.我有一个路由器/视图集/序列化器为Person资源创建一个端点:

/api/People/<id>/
Run Code Online (Sandbox Code Playgroud)

我想要某种方式触发对此资源的非幂等操作(例如send-email-to).在不必重新执行大量路由/序列化基础结构的情况下,我必须这样做的一个想法是向序列化器添加一个只写的布尔字段:

class PersonSerializer(serializers.ModelSerializer):
   send_email = serializers.BooleanField(write_only=True, required=False)
Run Code Online (Sandbox Code Playgroud)

然后向模型添加只写属性:

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)
Run Code Online (Sandbox Code Playgroud)

然后我可以PATCH到达有效载荷的终点send_email=True.

这是使用REST API完成类似RPC功能的最佳方法吗?这是在DRF中实现这一目标的最佳方法吗?理想情况下,我想解决这个问题,尽可能少地实现(即看看解决方案的代码行数是多少).send-email-to这不是我想要处理的唯一动作.

arg*_*aen 6

您可以使用drf提供的额外操作.在你的情况下,我会使用@detail_route.

像这样的东西:

@detail_route(methods=['post'])
def send_mail(self, request, pk=None):
    send_mail_to(pk)  # Write here your email function.
Run Code Online (Sandbox Code Playgroud)

您必须在Person视图集中定义此函数,因此,为了调用此函数,您必须在/ people/{person_id}/send_mailPOST,其中{person_id}是此人的主键.

作为旁注,由于此功能是从客户端同步调用的,可能需要一段时间才能回答,我建议您使用芹菜.这将允许您异步调用send_mail_to函数,而不会延迟用户响应.