如何使用rest_framework和Django获取多个对象的响应

时间:2013-08-29 10:57:28

标签: python django json django-rest-framework

我是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')

我尝试了什么:我认为我不需要修改模型和序列化程序,因为它在调用上述域时适用于单个对象。所以我尝试在LocationsViewSet中实现views.py并在urls.py中添加了一个新网址,但我失败了。知道如何实现它吗?也许只需在LocationAPIView中定义一个方法并更改定义类似于此的URL:

url(r'^all_locations/$', views.LocationAPIView.get_all_locations(), name='LocationAPIView')

提前致谢,我将不胜感激。

祝你好运, 迈克尔

1 个答案:

答案 0 :(得分:8)

首先,让我们暂时忘记视图集 - 它们使一些事情变得更简单,但它们还引入了一个额外的抽象层,我认为你现在不应该关注它。

您提到需要的第一件事是与当前详细端点等效的列表端点。你已经有了这个,你只需要在你现有的视图旁边引入一个额外的视图。

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

请注意,在生成响应时, 根本不需要使用序列化程序,您也可以在每个实例上提取所有必需字段,并在查看本身,但它是将模型实例映射到数据字典的一种很好的标准方法。

希望这会给你足够的开始。 :)