如何更改 Django Rest Framework 中的视图集检索响应?

新手上路,请多包涵

我目前正在开发一个使用 API 作为大学项目后端的 Web 应用程序。

我读过 DRF 是开发和部署 API 的最快和最简单的方法,我已经遵循了他们的整个官方

文档,我似乎不明白如何在他们的 ViewSet 和 Serializer 中执行以下操作。

这是我的 API 的一个端点,称为机场。

美国所有可用机场

返回指向美国可用机场的 json/csv 链接列表。

  • 网址

/airports

  • 方法:

GET

  • 成功响应:

    • 代码: 200

    内容:

   [
    {
        "airport": {
            "code": "PHL",
            "name": "Philadelphia, PA: Philadelphia International",
          "id": 123,
            "url": "/airports/123"
        },
    {
        "airport": {
            "code": "AHR",
            "name": "American Hour Rapid",
        "id": 125,
            "url": "/airports/125"
    }
    .
    .
    .
  ]

显示机场信息

返回 在特定机场运营的承运人的所有链接、 特定月份和年份的相关统计数据的链接以及机场航线的链接。如果未指定年份或月份,则默认为最近日期的日期。

  • 网址

/airports/:id

  • 方法:

GET

  • 网址参数

必需的:

id=[integer]

  • 成功响应:
 {
    "airport": {
      "code": "PHL",
      "name": "Philadelphia, PA: Philadelphia International",
      "id": 123,
      "url": "/airports/123"
    },
    "routes_link": "/airports/123/routes",
    "carriers": [
        {
          "id": 124,
          "url": "/carriers/124?airport_id=123",
          "statistics_url":"/airports/1carrier=124&statistics='flights'"
        },
        .
        .
        .
      ]
}

我能够执行 /airports 正确列出数据库中的所有可用机场,但是在使用 ViewSet 时,我不知道如何在尝试检索有关仅由 id 指定的一个机场的信息时“自定义”响应应用程序将动态生成路由,我打算添加到响应主体而不是模型中的另一个字段。

楷模:

 class Carrier(models.Model):
    code = models.CharField(max_length=10)
    name = models.TextField()
    #airports = models.ManyToManyField(Airport)

    def __str__(self):
        return self.name

class Airport(models.Model):
    code = models.CharField(max_length=10)
    name = models.TextField()
    carriers = models.ManyToManyField(Carrier, related_name='airports')

    def __str__(self):
        return self.name

序列化程序:

 class AirportSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.Airport
        fields = ('id', 'name', 'code', 'url')

class CarrierSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.Carrier
        fields = ('id', 'name', 'code', 'url')

看法:

 class AirportList(viewsets.ModelViewSet):
    queryset = models.Airport.objects.all()
    serializer_class = AirportSerializer
    # @Override something here?

任何人都可以告诉我如何使用 DRF 或任何我可以使用的学习材料来解决这个问题?

原文由 murthaA 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 685
2 个回答

如果你想修改 retrieve 的功能,你可以覆盖它的 retrieve 方法并做任何你想做的事。 mixin's 链接

class AirportList(viewsets.ModelViewSet):
    queryset = models.Airport.objects.all()
    serializer_class = AirportSerializer
    def retrieve(self, request, *args, **kwargs):
        # do your customization here
        instance = self.get_object()
        serializer = self.get_serializer(instance)
        return Response(serializer.data)

如何探索 DRF

我认为照顾任何新事物的最好方法是他们的代码库。对于 ModelViewset,您应该从 views 链接 开始,探索它提供的功能以及我如何自定义它们。

原文由 Shakil 发布,翻译遵循 CC BY-SA 4.0 许可协议

正如上面提到的 @Shakil ,您需要覆盖 retrieve 方法,但是要进行自定义响应,您需要包括 self.get_object()Try Except 中,如果没有它--- get_object 失败它将回退到默认响应并且没有机会自定义它。

所以你可以使用类似的东西……

首先是自定义响应类(例如失败案例)

 class ErrorResponse(Response):
    def __init__(self, *args, **kwargs):
        super(ErrorResponse,self).__init__(*args, **kwargs)
        self.status_code = 404
        self.data = {
            'success': False,
            'message': args[0].get('message')
        }

retrieve 方法

def retrieve(self, request, *args, **kwargs):
        try:
            instance = self.get_object()
        except Exception as e:
            return ErrorResponse({'message':str(e)})
        else:
            #any additional logic
            serializer = self.get_serializer(instance)
            return Response({'data': serializer.data})

原文由 Mostafa Garana 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进