我有一个汽车课
class Car(serializers.ModelSerializer):
engine = EngineSerializer(many=False, required=False)
owner = UserSerializer(many=False, required=False)
现在我想隐藏除了所有者以外的用户的引擎(应该在self.context['user'] == self.owner
进行检查。
我可以通过将引擎变成SerializerMethodField()
来实现这一目标class Car(serializers.ModelSerializer):
engine = serializers.SerializerMethodField()
owner = UserSerializer(many=False, required=False)
def get_engine(self, obj):
if self.context['user'] == self.owner:
return EngineSerializer(self.engine, many=False).data
else:
return None or so
但这会在创建+更新时产生问题。这是什么最好的做法?我不瞄准隐私,但只是想避免序列化引擎的成本(想象它需要很长时间才能序列化,对于除了拥有者以外的人来说它是无用的)
答案 0 :(得分:0)
在我看来,您可以使用自定义字段来处理此问题。
class EngineField(serializers.Field):
def to_representation(self, obj):
if self.context.get('user', None) == obj.owner:
return EngineSerializer(obj.engine, many=False).data
else:
return None or so
def to_internal_value(self, data):
do_something()
class Car(serializers.ModelSerializer):
engine = EngineField()
owner = UserSerializer(many=False, required=False)
答案 1 :(得分:0)
Django Rest Framework很容易扩展,只需看看内部:)
例如,如果您使用的是内部使用RetrieveModelMixin的任何类型的视图/视图集, 检查RetrieveModelMixin.retrieve()方法。 它调用GenericAPIView.get_serializer()方法,将对象实例作为参数传递。
您可以覆盖该方法并根据instance.owner字段返回不同的序列化程序对象。
在视图中更改此方法后,此行为将适用于对单个对象进行操作的任何mixin。
对于queryset,它会有点棘手,但我认为如果序列化一个引擎代价很高,你可能会在返回汽车列表时完全避免序列化这个字段。
示例代码(未经过测试,肯定不是完美的,但您会明白这一点):
class CarView(rest_framework.generics.RetrieveUpdateDestroyAPIView):
def get_serializer(self, *args, **kwargs):
# instance returned by self.get_object is passed as first arg
# in mixins used by RetrieveUpdateDestroyAPIView
car = args[0]
if self.request.user == car.owner:
serializer_class = ComplexCarSerializerWithEngineField
else:
serializer_class = SimpleCarSerializerWithNoEngineField
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_object(self):
...