假设我的一个POSTed DRF API参数是一个允许我识别对象的字符串。然后,我的序列化程序使用此字段来验证字符串(以及其他一些POSTed参数)并获取底层对象(作为验证的最后部分)。所以,在validate()
的末尾,我已经在我的视图中查找了我需要使用的对象,但我无法弄清楚如何在视图中访问此对象。如果我在data['my_object'] = my_object
的末尾设置了validate()
,那么在我的视图中serializer.is_valid()
返回后,它最终只是我的对象的名称。
如何将序列化程序中的对象“传递”回视图? (或者,如果有理由不这样做,那么避免在数据库中查找同一个对象两次的最佳做法是什么?)
# serializer
class MySerializer(serializers.Serializer):
my_string_param = serializers.CharField()
another_param = serializers.CharField()
...
def validate(self, data):
# validate data['my_string_param'] and fetch my_object
try:
my_object = MyModel.objects.get(
field1=data['my_string_param'], field2=data['another_param'])
except MyModel.DoesNotExist:
raise ValidationError('Please check your params and try again.')
data['my_object'] = my_object # doesn't work: is a string when later accessed in the view
return data
# view
class MyView(APIView):
...
def post(self, request, format=None):
serializer = MySerializer(data=request.data)
if serializer.is_valid():
# don't want to fetch from db again
# my_object = MyModel.objects.get(field1=serializer.data['my_string_param'], field2=serializer.data['another_param'])
# would like to reuse already fetched object, but it's just its str name
my_object = serializer.data['my_object']
# do stuff with my_object and return
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
答案 0 :(得分:1)
您可以将获取的对象设置为序列化程序属性,然后在视图中访问此属性。这样做可以避免在视图中出现额外的查询。
# serializer
class MySerializer(serializers.Serializer):
my_string_param = serializers.CharField()
another_param = serializers.CharField()
...
def validate(self, data):
# validate data['my_string_param'] and fetch my_object
try:
# set the object as an attribute
self.my_object = MyModel.objects.get(
field1=data['my_string_param'], field2=data['another_param'])
except MyModel.DoesNotExist:
raise ValidationError('Please check your params and try again.')
return data
# view
class MyView(APIView):
...
def post(self, request, format=None):
serializer = MySerializer(data=request.data)
if serializer.is_valid():
my_object = serializer.my_object # access the already retrieved object
# do stuff with my_object and return
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)