感谢 @ans2human 提供此答案背后的灵感。
这是一种对我很有用的新方法。我有几个需要在嵌套关系中过滤掉的Model
s 。is_active = BooleanField(...)
注意:此解决方案不会过滤掉非列表字段的结果。为此,你应该看看你的queryset
主View
工作的核心是通过在 custom和伴随to_representation()
的 custom 上重载函数来完成的:ListSerializer
many_init
ModelSerializer
class FilteredListSerializer(serializers.ListSerializer):
filter_params:dict
def __init__(self, *args, filter_params:dict={"is_active":True}, **kwargs):
super().__init__(*args, **kwargs)
self.filter_params = filter_params
def set_filter(self, **kwargs):
self.filter_params = kwargs
def to_representation(self, data):
data = data.filter(**self.filter_params)
return super().to_representation(data)
class FilteredModelSerializer(serializers.ModelSerializer):
LIST_SERIALIZER_KWARGS = serializers.LIST_SERIALIZER_KWARGS + ("filter_params",)
LIST_ONLY_KWARGS = ('allow_empty', 'filter_params')
@classmethod
def many_init(cls, *args, **kwargs):
list_kwargs = dict()
for arg in cls.LIST_ONLY_KWARGS:
value = kwargs.pop(arg, None)
if value is not None:
list_kwargs[arg] = value
child_serializer = cls(*args, **kwargs, **({"read_only":True} if "read_only" not in kwargs else dict()))
list_kwargs['child'] = child_serializer
list_kwargs.update({
key: value for key, value in kwargs.items()
if key in cls.LIST_SERIALIZER_KWARGS
})
meta = getattr(cls, 'Meta', None)
list_serializer_class = getattr(meta, 'list_serializer_class', FilteredListSerializer)
return list_serializer_class(*args, **list_kwargs)
然后,您ModelSerializer
对任何视图的自定义将改为扩展FilteredModelSerializer
。
class ChildSerializer(FilteredModelSerializer):
is_active = BooleanField() # not strictly necessary, just for visibilty
... # the rest of your serializer
class ParentSerializer(serializers.ModelSerializer):
children = ChildSerializer(many=True)
...# the rest of your parent serializer
现在,children
ParentSerializer 上的字段将过滤is_active = True
.
如果您有想要应用的自定义查询,您可以通过提供标准格式dict
的过滤器参数来实现:queryset
class ParentSerializer(serializers.ModelSerializer):
children = ChildSerializer(many=True, filter_params={"my_field":my_value, "my_datetime__gte": timezone.now()})
...# the rest of your parent serializer
或者,也可以在实例化字段之后使用该set_filter(...)
方法,就像这样。FilteredListSerializer
这将为原始QuerySet.filter(...)
样式生成更熟悉的格式:
class ParentSerializer(serializers.ModelSerializer):
children = ChildSerializer(many=True)
children.set_filter(my_field=my_value, my_datetime__gte=timezone.now())
...# the rest of your parent serializer