Django REST Framework:在验证期间获取 ID/URL?

Django REST Framework: Get ID/URL during validation?

我有一个HyperlinkedModelSerializer。要正确实现其 validate 方法,我需要访问对象的 主键 URL正在验证——如果它有一个,即如果它正在编辑,而不是创建。正确的做法是什么?

我尝试了很多方法,但唯一可行的方法是在序列化程序实例化到它的 id 字段时获取对象的 ID:

class BoxSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Box
        fields = ('id', 'name', 'url')

    def __init__(self, *args, **kwargs):
        super(BoxSerializer, self).__init__(*args, **kwargs)
        self.id = None \
            if len(args) != 1 or not isinstance(args[0], Box) \
            else args[0].id

    def validate(self, data):
        print(data)
        return data

从序列化程序的 validate 方法中访问正在验证的对象的 ID/URL 的正确方法是什么? data['id']data['url'] 都不存在。


urls.py:

urlpatterns = [
    url(r'(?P<pk>[0-9]+)/$', views.BoxDetail.as_view(), name='box-detail'),
]

views.py:

class BoxDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = Box.objects.all()
    serializer_class = BoxSerializer

使用 context 属性调用序列化程序。

serializer = BoxSerializer(queryset, context={'request': self.request}, ...)

现在您可以使用

validate 函数访问 request 对象
self.context['request']['id']

您可以访问self.instance正在编辑的对象的id

来自 Accessing the initial data and instance:

上的 DRF 序列化程序文档

When passing an initial object or queryset to a serializer instance, the object will be made available as .instance. If no initial object is passed then the .instance attribute will be None.

由于您使用的是 HyperLinkedModelSerializer,因此在 PUT 请求的情况下,您将有权访问正在编辑的对象,作为在序列化程序上设置的 instance 属性。您可以使用此 instance 属性通过执行 self.instance.id 来访问正在编辑的对象的 id

您可以在 validate() 函数中编写您的验证逻辑,然后在变量 object_id 中获取对象 ID 之后。这不会影响创建请求,因为 instance 不会在序列化器上设置。

class BoxSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Box
        fields = ('id', 'name', 'url')

    def validate(self, data):
        if self.instance: # 'instance' will be set in case of `PUT` request i.e update
            object_id = self.instance.id # get the 'id' for the instance
            # write your validation logic based on the object id here

        return data

访问对象 ID 的另一种方法 是从序列化程序 context 字典中的 view 对象访问 kwargs

my_view = self.context['view'] # get the 'view' object from serializer context
object_id = my_view.kwargs.get('pk') # access the 'view' kwargs and lookup for 'pk'