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

时间:2015-07-28 11:31:08

标签: django django-views django-rest-framework

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

我尝试了很多东西,但唯一有效的方法是在将序列化程序实例化到id字段时获取对象ID的hack:

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的正确方法是什么? <{1}}和data['id']都不存在。

data['url']

urls.py

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

views.py

2 个答案:

答案 0 :(得分:4)

您可以id访问正在修改的对象的self.instance

来自Accessing the initial data and instance:

上的DRF序列化程序文档
  

将初始对象或查询集传递给序列化程序实例时,   该对象将以.instance的形式提供。如果没有初始对象   传递后,.instance属性将为None

由于您使用的是HyperLinkedModelSerializer,因此如果PUT请求作为序列化程序上设置的instance属性,您将可以访问正在编辑的对象。您可以使用此instance属性通过id访问正在编辑的对象的self.instance.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的另一种方式是访问序列化程序kwargs字典中view对象的context

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' 

答案 1 :(得分:0)

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

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

现在,您可以使用

request功能访问validate对象
self.context['request']['id']