【问题标题】:Django Rest Framework: How to Dynamically return subset of fieldsDjango Rest Framework:如何动态返回字段子集
【发布时间】:2021-08-20 14:58:04
【问题描述】:

我想按字段名称过滤并取回一个子集,而不是取回我所有的字段名称。例如这里我按 id 和 name 过滤。它应该只以 json 格式返回这两个维度。 我在网站上找到了许多解决方案,并且我已经按照建议做了完全一样的事情,但我没有得到预期的结果。你能帮帮我吗?

我的 urls.py:

router = routers.DefaultRouter()
urlpatterns = [
    path('', include(router.urls)),
    path('edges/', edge_list),
    path('edges/<int:pk>/', edge_detail),
    path('network/<int:pk>/edges/', edges_of_a_network),
]

我的看法

@api_view(['GET', 'POST'])
def edge_list(request):
    """
    List all edges of all networks, or create a new edge.
    """
    if request.method == 'GET':
        edges = Edge.objects.all()
        serializer = EdgeSerializer(edges, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = EdgeSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.error, status=status.HTTP_400_BAD_REQUEST)

这里是来自https://www.django-rest-framework.org/api-guide/serializers/#example的复制过去示例

class DynamicFieldsModelSerializer(serializers.ModelSerializer):
    """
    A ModelSerializer that takes an additional `fields` argument that
    controls which fields should be displayed.
    """

    def __init__(self, *args, **kwargs):
        # Don't pass the 'fields' arg up to the superclass
        fields = kwargs.pop('fields', None)

        # Instantiate the superclass normally
        super(DynamicFieldsModelSerializer, self).__init__(*args, **kwargs)

        if fields is not None:
            # Drop any fields that are not specified in the `fields` argument.
            allowed = set(fields)
            existing = set(self.fields)
            for field_name in existing - allowed:
                self.fields.pop(field_name)

我想过滤字段的序列化程序类。

class EdgeSerializer(DynamicFieldsModelSerializer, serializers.ModelSerializer):
    source = serializers.SerializerMethodField(method_name='get_node_source')
    target = serializers.SerializerMethodField(method_name='get_node_target')
    road_type = serializers.SerializerMethodField(
                                        method_name='get_road_type_id')

    class Meta:
        model = Edge
        fields = (
            'id', 'edge_id', 'name', 'length', 'speed',
            'lanes', 'param1', 'param2', 'param3', 'network',
            'road_type', 'source', 'target'
        )

    def get_road_type_id(self, instance):
        return {"id": instance.road_type.road_type_id,
                "name": instance.road_type.name}

    def get_node_source(self, instance):
        return {"node_id":instance.source.node_id, "node_name": instance.source.name}

    def get_node_target(self, instance):
        return {"node_id":instance.target.node_id, "node_name": instance.target.name}

【问题讨论】:

    标签: django django-rest-framework django-serializer django-filter drf-queryset


    【解决方案1】:

    在您的视图中,您是如何使用序列化程序的?你可以初始化为:

    
    fields = request.query_params.get('fields')
    fields_cleaned = [field.replace('-', '') for field in fields]
    ser = EdgeSerializer(fields=fields_cleaned, instance=queryset, many=True)
    print(ser.data)
    

    【讨论】:

    • 我刚刚添加了视图。如果没有过滤器,我会保留返回所有字段的相同视图。我错了吗?
    • @aba2s 您的代码显示所有字段,看起来还不错。如果fields_cleaned 不为空,您可以简单地编写if 语句并传递fields 参数。例如:`如果清理:SerializerClass(fields, qs) else: SerializerClass(qs)
    • @raviashikiri,我听从了你的建议,但没有得到预期的结果。我错过了一些我不明白的东西。我在下面添加了视图
    【解决方案2】:
    @api_view(['GET', 'POST'])
    def edge_list(request):
        """
        List all edges of all networks, or create a new edge.
        """
        if request.method == 'GET':
            edges = Edge.objects.all()
            fields = request.query_params.get('fields')
            fields_cleaned = [field.replace('-', '') for field in fields]
            if not fields_cleaned:
                serializer = EdgeSerializer(fields=fields, instance=edges, many=True)
            else:
                serializer = EdgeSerializer(instance=edges, many=True)
            return Response(serializer.data)
    
        elif request.method == 'POST':
            serializer = EdgeSerializer(data=request.data)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.error, status=status.HTTP_400_BAD_REQUEST)
    

    【讨论】:

      猜你喜欢
      • 2014-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-03
      相关资源
      最近更新 更多