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'
我有一个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 beNone
.
由于您使用的是 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'