我目前正在开发一个Web应用程序,该应用程序使用API作为大学项目的后端。
我已经读到DRF是开发和部署API的最快和最简单的方法,我已经遵循了他们的整个官方规定
文档,我似乎不太了解如何在他们的ViewSet和Serializer中进行以下操作。
这是我的API的一个端点,称为机场。
返回到美国可用机场的链接的json / csv列表。
URL
/airports
方法:
GET
成功响应:
[
{
"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
URL参数
必填:
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或我可以使用的任何学习材料来实现这一目标?
答案 0 :(得分:2)
如果您想修改ModelViewset的retreive
功能,则可以覆盖它的retreive
方法,并做您想做的事情。 mixin's
link
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)
我认为,照顾任何新事物的最佳方法是他们的代码库。对于ModelViewset,您应该从views
link开始,探索它提供的功能以及如何自定义它们。
答案 1 :(得分: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})