如何使用 rest_framework 和 Django 获取多个对象的响应
Posted
技术标签:
【中文标题】如何使用 rest_framework 和 Django 获取多个对象的响应【英文标题】:How to get a response of multiple objects using rest_framework and Django 【发布时间】:2013-09-01 18:39:12 【问题描述】:我是 Django 框架和 Django REST 框架的新手,但我的基本设置和实现正在运行。当我为单个对象调用域时,它就像一个魅力,例如http://mydomain.com/location/1(其中 1 是主键)。这给了我这样的 JSON 响应:
"id": 1, "location": "Berlin", "country": 2
.. 和http://mydomain.com/country/2 回复如下:
"id": 2, "country": "Germany"
我需要什么: 现在我需要获取多个位置,例如调用域http://mydomain.com/all_locations/ 时。我希望得到这样的回应:
[
"id": 1, "location": "Berlin", "country": 2,
"id": 2, "location": "New York", "country": 4,
"id": 3, "location": "Barcelona", "country": 5,
"id": 4, "location": "Moscow", "country": 7
]
这是可选的:第二步,当我致电http://mydomain.com/mix_all_locations_countries/ 时,我希望在一个响应中包含多个国家和地区,例如:
[
"locations":
"id": 1, "location": "Berlin", "country": 2,
"id": 2, "location": "New York", "country": 4,
"id": 3, "location": "Barcelona", "country": 5,
"id": 4, "location": "Moscow", "country": 7
,
"countries":
"id": 1, "country": "Brazil"
"id": 2, "country": "Germany",
"id": 3, "country": "Portugual"
"id": 4, "country": "USA",
"id": 5, "country": "Spain",
"id": 6, "country": "Italy"
"id": 7, "country": "Russia"
]
这是我目前的实现(仅显示位置的实现):
在 models.py 中:
class Location(models.Model):
# variable id and pk are always available
location = models.CharField(max_length=100)
country = models.ForeignKey("Country")
在serializers.py中:
class LocationsSerializer(serializers.ModelSerializer):
country_id = serializers.Field(source='country.id')
class Meta:
model = Location
fields = (
'id',
'location',
'country_id',
)
在 views.py 中:
class LocationAPIView(generics.RetrieveAPIView):
queryset = Location.objects.all()
serializer_class = LocationSerializer
在 urls.py 中:
url(r'^location/(?P<pk>[0-9]+)/$', views.LocationAPIView.as_view(), name='LocationAPIView')
我尝试了什么:我认为我不需要修改模型和序列化程序,因为它在调用上述域时适用于单个对象。所以我尝试在views.py
中实现一个LocationsViewSet
并在urls.py
中添加一个新的url,但我失败了。知道如何实施吗?也许只是在 LocationAPIView 中定义一个方法并更改定义一个类似这样的 url:
url(r'^all_locations/$', views.LocationAPIView.get_all_locations(), name='LocationAPIView')
提前致谢,如有任何帮助,我将不胜感激。
最好的问候, 迈克尔
【问题讨论】:
【参考方案1】:首先,让我们暂时忘记视图集 - 它们让一些事情变得更简单,但它们也引入了额外的抽象层,我认为你现在不应该关心。
您提到的第一件事是与您当前的详细端点等效的列表端点。您几乎已经掌握了这一点,您只需要在现有视图旁边引入一个额外的视图。
views.py
:
class LocationListAPIView(generics.ListAPIView):
queryset = Location.objects.all()
serializer_class = LocationSerializer
class LocationDetailAPIView(generics.RetrieveAPIView):
queryset = Location.objects.all()
serializer_class = LocationSerializer
现在在你的 URLconf 中连接两个视图。
urls.py
:
url(r'^location/$', views.LocationListAPIView.as_view(), name='location-list'),
url(r'^location/(?P<pk>[0-9]+)/$', views.LocationDetailAPIView.as_view(), name='location-detail')
请注意,我还更改了 URL 名称样式,使其更符合通常的 Django 约定。
接下来,您想要组合位置 + 国家/地区视图。您不仅可以为此使用现有的通用视图,因为它是相当自定义的行为,但是为...编写视图很容易......
views.py
:
class CombinedAPIView(APIView):
def get(self, request):
locations = Location.objects.all()
countries = Country.objects.all()
location_serializer = LocationSerializer(locations, many=True)
country_serializer = CountrySerializer(countries, many=True)
return Response(
'countries': country_serializer.data,
'locations': location_serializer.data
)
然后将视图连接起来。
urls.py
:
url(r'^combined/$', views.CombinedAPIView.as_view(), name='combined-list')
请注意,在生成响应时,您根本不需要 使用序列化程序,您也可以在每个实例上提取所有必需的字段,在view 本身,但这是将模型实例映射到数据字典的一种很好的标准方法。
希望这会给您足够的入门知识。 :)
【讨论】:
谢谢汤姆!我尝试了您的方法,使用 CombinedAPIView 的第二部分效果很好!但是,第一个建议不起作用。可能是因为我使用的是 generics.RetrieveAPIView??这是错误:Expected view LocationListAPIView to be called with a URL keyword argument named "pk". Fix your URL conf, or set the
.lookup_field` 属性在视图上正确。`
之后我只是尝试使用 CombinedAPIView 来测试 url:url(r'^location/$', views.CombinedAPIView.as_view(), name='location-list'),
这可行,但不是解决方案 :) 希望您能帮我解决这个错误。提前致谢。
好的,我改用 APIView 解决了这个问题。无论如何,您知道如何使用 generics.RetrieveAPIView 修复它吗?这是对我有用的解决方案:class LocationListAPIView(APIView): def get(self, request): locations = Location.objects.all() location_serializer = LocationSerializer(locations, many=True) return Response( 'locations': location_serializer.data, )
"generics.RetrieveAPIView" - 我刚刚纠正了一个错字,列表视图应该扩展 generics.ListAPIView
。以上是关于如何使用 rest_framework 和 Django 获取多个对象的响应的主要内容,如果未能解决你的问题,请参考以下文章
Django.rest_framework:如何序列化一对多?
如何从 rest_framework 序列化程序获得漂亮的输出
Django - 如何通过 API 端点使用 rest_framework 动态地将多个对象添加到数据库中
如何使 rest_framework 序列化器禁止多余的字段?
django框架学习六:优化views.py文件,使用rest_framework中的APIVew和Response返回