如何更改 Django Rest Framework 中的视图集检索响应?
How to change viewset retrieve response in Django Rest Framework?
我目前正在开发一个使用 API 作为大学项目后端的 Web 应用程序。
而且我读到 DRF 是开发和部署 API 的最快和最简单的方法,我已经遵循了他们的整个官方
文档,我似乎不明白如何在他们的 ViewSet 和 Serializer 中执行以下操作。
这是我的 API 的一个端点,称为机场。
美国可用的所有机场
Returns json/csv link 美国可用机场列表。
URL
/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"
}
.
.
.
]
显示机场信息
Returns 所有 link 到在特定机场运营的航空公司, link 到特定月份的相关统计数据和年份还有一条link到机场的路线。如果未指定年份或月份,则默认为最近的日期。
- URL
/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 时,我不知道如何 "customize" 在尝试仅检索有关一个机场的信息时做出响应由 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 或任何类型的学习来解决这个问题 material 我可以使用吗?
如果您想修改 ModelViewset 的 retrieve
功能,您可以覆盖它的 retrieve
方法并做任何您想做的事。 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)
如何探索 DRF
我认为管理任何新事物的最佳方式是他们的代码库。对于 ModelViewset,您应该从 views
link 开始,探索它提供的功能以及我如何自定义它们。
如上面提到的@ 你需要覆盖 retrieve
方法,但是要进行自定义响应你需要在 Try Except
块中包含 self.get_object()
,如没有它,如果 get_object
失败,它将回退到默认响应,并且没有机会自定义它。
所以你可以使用类似的东西......
首先是自定义响应 class(例如失败案例)
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})
这可能不是问题的确切解决方案,但这是我的解决方案,您默认定义了 lookup_field = "uuid"
,但您还想使用 slug
进行查找而不定义新的 url 配置(也许你对 ViewSet 使用 DefaultRouter)。
class MyViewSet(ModelViewSet):
lookup_field = "uuid"
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
lookup_value = self.kwargs["uuid"]
if is_valid_uuid(lookup_value):
filter = dict(uuid=lookup_value)
else:
filter = dict(slug=lookup_value)
obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj
我目前正在开发一个使用 API 作为大学项目后端的 Web 应用程序。
而且我读到 DRF 是开发和部署 API 的最快和最简单的方法,我已经遵循了他们的整个官方
文档,我似乎不明白如何在他们的 ViewSet 和 Serializer 中执行以下操作。
这是我的 API 的一个端点,称为机场。
美国可用的所有机场
Returns json/csv link 美国可用机场列表。
URL
/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" } . . . ]
- 代码: 200
显示机场信息
Returns 所有 link 到在特定机场运营的航空公司, link 到特定月份的相关统计数据和年份还有一条link到机场的路线。如果未指定年份或月份,则默认为最近的日期。
- URL
/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 时,我不知道如何 "customize" 在尝试仅检索有关一个机场的信息时做出响应由 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 或任何类型的学习来解决这个问题 material 我可以使用吗?
如果您想修改 ModelViewset 的 retrieve
功能,您可以覆盖它的 retrieve
方法并做任何您想做的事。 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)
如何探索 DRF
我认为管理任何新事物的最佳方式是他们的代码库。对于 ModelViewset,您应该从 views
link 开始,探索它提供的功能以及我如何自定义它们。
如上面提到的@retrieve
方法,但是要进行自定义响应你需要在 Try Except
块中包含 self.get_object()
,如没有它,如果 get_object
失败,它将回退到默认响应,并且没有机会自定义它。
所以你可以使用类似的东西......
首先是自定义响应 class(例如失败案例)
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})
这可能不是问题的确切解决方案,但这是我的解决方案,您默认定义了 lookup_field = "uuid"
,但您还想使用 slug
进行查找而不定义新的 url 配置(也许你对 ViewSet 使用 DefaultRouter)。
class MyViewSet(ModelViewSet):
lookup_field = "uuid"
def get_object(self):
queryset = self.get_queryset() # Get the base queryset
queryset = self.filter_queryset(queryset) # Apply any filter backends
lookup_value = self.kwargs["uuid"]
if is_valid_uuid(lookup_value):
filter = dict(uuid=lookup_value)
else:
filter = dict(slug=lookup_value)
obj = get_object_or_404(queryset, **filter) # Lookup the object
self.check_object_permissions(self.request, obj)
return obj