如何在Django Rest框架中更改viewset检索响应?

如何在Django Rest框架中更改viewset检索响应?,django,python-3.x,django-rest-framework,django-views,api-design,Django,Python 3.x,Django Rest Framework,Django Views,Api Design,我目前正在开发一个Web应用程序,它使用API作为一个大学项目的后端 我读过DRF是开发和部署API的最快、最简单的方法,我已经遵循了他们的整个官方计划 文档,我似乎不明白如何在他们的视图集和序列化程序中执行以下操作 这里是我的API的一个端点,叫做airports 美国所有可用机场 返回指向美国可用机场的json/csv链接列表 URL /机场 方法: GET 成功响应: 代码:200 内容: 显示机场信息 返回指向在特定机场运营的承运人的所有链接,指向特定月份和年份的相关统计数据

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

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

文档,我似乎不明白如何在他们的视图集和序列化程序中执行以下操作

这里是我的API的一个端点,叫做airports

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

  • URL

    /机场

  • 方法:

    GET

  • 成功响应:

    • 代码:200
      内容:

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

  • URL
/airports/:id

  • 方法:
GET

  • URL参数

    必填项:

    id=[integer]

  • 成功响应:

我能够正确地列出数据库中所有可用的机场,但在使用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')
视图:


任何人都有关于我如何使用DRF或我可以使用的任何类型的学习材料来实现这一点的提示吗?

如果您想修改ModelViewset的
检索
功能,您可以覆盖其
检索
方法,然后做任何您想做的事情<代码>mixin's

如何探索DRF
我认为处理任何新事物的最好方法是他们的代码库。对于ModelViewset,您应该从
视图
开始,探索它提供了哪些功能,以及如何自定义它们

如果您想修改ModelViewset的
检索
功能,您可以覆盖其
检索
方法并执行任何您想要的操作<代码>mixin's

如何探索DRF 我认为处理任何新事物的最好方法是他们的代码库。对于ModelViewset,您应该从
视图
开始,探索它提供了哪些功能,以及如何自定义它们

如上所述,您需要覆盖
retrieve
方法,但要做出自定义响应,您需要在
Try Except
块中包含
self.get\u object()
,因为如果没有它,如果
get\u object
失败,它将返回到默认响应,并且没有机会进行自定义
所以你可以用这样的东西

首先是自定义响应类(例如,对于失败的情况)


以及
检索
方法

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})
如上所述,@需要覆盖
retrieve
方法,但要做出自定义响应,需要在
Try Except
块中包含
self.get\u object()
,因为如果没有它,如果
get\u object
失败,它将返回默认响应,并且没有机会自定义它
所以你可以用这样的东西

首先是自定义响应类(例如,对于失败的情况)


以及
检索
方法

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})

重写retrieve对我不起作用,即使在修改它之后,我也会得到相同的响应,即使我返回“Hello”。@L先生,也许你重写了错误的方法。如果只是返回正在考虑的模型的单个实例,则需要重写
retrieve()
。如果要返回实例列表,请尝试重写
list()
方法。您可以在上面答案中共享的mixin链接中找到它的定义。重写retrieve对我不起作用,即使在修改它之后,我也会得到相同的响应,即使我返回“Hello”。@Mr.L可能您重写了错误的方法。如果只是返回正在考虑的模型的单个实例,则需要重写
retrieve()
。如果要返回实例列表,请尝试重写
list()
方法。您可以在上面答案中共享的mixin链接中找到它的定义。
class AirportList(viewsets.ModelViewSet):
    queryset = models.Airport.objects.all()
    serializer_class = AirportSerializer
    # @Override something here?
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)
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')
        }
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})