DRF :将附加信息注入 request.data 的通用方法

DRF : Generic way to inject additional info into request.data

我的情况是我有一个端点 samples,它通过 ModelViewSet 表示模型 sample

我的目标是,当用户 POST 使用数据

攻击此端点时

喜欢

{
    "a":1,
    "b":2 ,
    "c":3
}

我希望能够 override/add key:value 与 create 方法中存储在 request.data 中的传入有效载荷配对。

这不能通过简单地访问 request.data 来完成,因为它是一个不可变的 QueryDict

此外,我无法在 perform_create() 方法中实现这一点,因为我可能注入的数据是验证关键的。

目前我遇到了以下解决方案,需要我重写完整的 create() 方法:

class MyViewSet(viewsets.ModelViewSet):
    queryset = Sample.objects.all()
    serializer_class = MSampleSerializer
    name = "samples"

    def add_info(self, request):
        ...
        <acquire_info>
        ...
        data = request.data.dict()
        data["s"] = <info1>
        data["r"] = <info1>
        data["t"] = <info1>
        return data


    def create(self, request, *args, **kwargs):
        data = self.add_info(request)
        serializer = self.get_serializer(data=data)
        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(
            serializer.data, status=status.HTTP_201_CREATED, headers=headers
        )
  1. 在调用任何操作方法(如 create()put() 之前,是否有通用的方法来编辑 request.data

  2. 如果不是1.);有不同的可能性吗?

提前致谢。

如果您不想每次都重写整个视图,您可以使用序列化程序的 .to_representation().to_internal_value() 方法。

并且由于您也想验证数据,.to_representation() 可能是解决此问题的方法。

来自文档:

If you need to alter the serialization or deserialization behavior of a serializer class, you can do so by overriding the .to_representation() or .to_internal_value() methods.

.to_representation(self, obj) takes the object instance that requires serialization, and should return a primitive representation. Typically this means returning a structure of built-in Python datatypes. The exact types that can be handled will depend on the render classes you have configured for your API.

示例:

def to_representation(self, instance):
    """Convert `username` to lowercase."""
    ret = super().to_representation(instance)
    ret['username'] = ret['username'].lower()
    return ret

Advanced serializer usage: Overriding serialization and deserialization behavior