我有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
答案 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']