11

Używamy Django REST Framework dla naszego interfejsu API i mamy potrzebę stronicowania pól relacji, które zwracają wiele elementów.Pośredni związek w strukturze REST Django?

Aby wykazać na podstawie przykładów podobnych do tych w documentation:

class TrackSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Track 
     fields = ('order', 'title') 

class AlbumSerializer(serializers.ModelSerializer): 
    tracks = TrackSerializer(many=True) 

    class Meta: 
     model = Album 
     fields = ('album_name', 'artist', 'tracks') 

Przykład odcinkach wyjście na płytę:

{ 
    'album_name': 'The Grey Album', 
    'artist': 'Danger Mouse' 
    'tracks': [ 
     {'order': 1, 'title': 'Public Service Annoucement'}, 
     {'order': 2, 'title': 'What More Can I Say'}, 
     {'order': 3, 'title': 'Encore'}, 
     ... 
    ], 
} 

Staje się to problemem, gdy istnieje znaczy setki ścieżek na album. Czy w tym przypadku istnieje sposób na paginację "ścieżek"?

Wiem, że w takich przypadkach "utwory" powinny wskazywać na URL interfejsu API, który po prostu zwraca ścieżki do określonego albumu - który z kolei może być łatwo paginowany. Wadą tego podejścia jest dodatkowe żądanie (a więc opóźnienie itd.) Wymagane do uzyskania nawet pierwszych kilku utworów. W naszym przypadku ważne jest, abyśmy mogli uzyskać co najmniej kilka ścieżek za pomocą pojedynczego żądania do interfejsu Album API, a następnie dynamicznie ładować resztę ścieżek w razie potrzeby.

Czy DRF oferuje jakąś określoną funkcję lub wzór? Czy są jakieś prace dookoła?

+3

Uwaga na przyszłość. To było kontynuowane w [tym wątku] (https://groups.google.com/d/msg/django-rest-framework/UtVRH8mHwmU/C6C5OhkEQ80J) na liście dyskusyjnej Dmygo REST. –

Odpowiedz

8

odpowiedzi skopiowane z Toma linku powyżej w przypadku przyszłej bitowym rot:

class TrackSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Track 
     fields = ('order', 'title') 

class PaginatedTrackSerializer(pagination.PaginationSerializer): 
    class Meta: 
     object_serializer_class = TrackSerializer 

class AlbumSerializer(serializers.ModelSerializer): 

    tracks = serializers.SerializerMethodField('paginated_tracks') 


    class Meta: 
     model = Album 
     fields = ('album_name', 'artist', 'tracks') 


    def paginated_tracks(self, obj): 
     paginator = Paginator(obj.tracks.all(), 10) 
     tracks = paginator.page(1) 

     serializer = PaginatedTrackSerializer(tracks) 
     return serializer.data 
+0

Ale jak uzyskać parametr rozmiaru strony i parametr strony w ścieżce paginated_tracks? – scott

+1

Ok, rozumiem. 'request = self.context ['request']' – scott

+0

FYI - 'Paginator' pochodzi z' from django.core.paginator import Paginator'. –

8

Od DRF 3.1 PaginationSerializer nie jest obsługiwany. Oto rozwiązanie.


settings.py

REST_FRAMEWORK = { 
    'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 
    'PAGE_SIZE': 5 
} 

serializers.py

from myapp.models import Album, Track 
from rest_framework import pagination, serializers 

class AlbumSerializer(serializers.HyperlinkedModelSerializer): 
    tracks = serializers.SerializerMethodField('paginated_tracks') 

    class Meta: 
     model = Album 

    def paginated_tracks(self, obj): 
     tracks = Track.objects.filter(album=obj) 
     paginator = pagination.PageNumberPagination() 
     page = paginator.paginate_queryset(tracks, self.context['request']) 
     serializer = TrackSerializer(page, many=True, context={'request': self.context['request']}) 
     return serializer.data 

class TrackSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = Track 

czy można zastąpić def paginated_tracks dla

from rest_framework.settings import api_settings 

    def get_paginated_tracks(self, obj): 
     tracks = Track.objects.filter(album=obj)[:api_settings.PAGE_SIZE] 
     serializer = TrackSerializer(tracks, many=True, context={'request': self.context['request']}) 
     return serializer.data 

Wymaga to nawet mniej zapytań niż powyżej.

+0

działa to dobrze dla pojedynczego albumu, ale jeśli pobierasz listę albumów (która również wymaga stronicowania), parametry stronicowania ustawione w obiekcie żądania prawdopodobnie nie powinny być używane do stronicowania ścieżek. – eugene

0

Tworzę api w plikach widoku i otrzymuję komunikat o błędzie " Exception Type: KeyError Exception Value:'request'". Gdzie ustawiłeś request? Mój kod API:

class getAlbumsList(APIView): 
    def get(self,request,token,format=None): 
     page = request.query_params.get('page') 
     tracks = Albums.objects.filter(designer=2)[:3] 
     serializer = AlbumSerializer(categorys, many=True) 
     return serializer.data 
1

Metody Malcolm Box i Deepak Prakash nie może pomóc serializer obiekty relathionship, ale tylko jako @eugene powiedziałem wcześniej, to działa tylko na jednym Alum. Przez Albumy możemy to zrobić:

serializers.py

class TrackSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Track 
     fields = ('order', 'title') 

class AlbumSerializer(serializers.ModelSerializer): 
    tracks = TrackSerializer(many=True) 

    class Meta: 
     model = Album 
     fields = ('album_name', 'artist', 'tracks') 
     depth=1 

apis.py

class getAPIView(generics.ListAPIView): 
    serializer_class=TrackSerializer 
    filter_backends = (filters.OrderingFilter,) 
    def get_queryset(self): 
     queryset=Track.objects.all() 
     return queryset 
    def list(self, request, *args, **kwargs): 
     queryset = self.filter_queryset(self.get_queryset()) 
     page = self.paginate_queryset(queryset) 
     serializer = self.get_serializer(page, many=True) 
     data=serializer.data 
     albums=Album.objects.values_list('album_name').all() 
     trackObjs=[] 
     albumObjs=[] 
     self.categoryKeyList(albums,albumObjs) 
     if page is not None: 
      for p in page: 
       for n,i in enumerate(albums): 
        if re.search(str(p.alum),str(i)): 
         albumObjs[n]['track'].append(p) 
     data={} 
     data['count']=self.get_paginated_response(self).data['count'] 
     data['next']=self.get_paginated_response(self).data['next'] 
     data['previous']=self.get_paginated_response(self).data['previous'] 
     data['pageNumber'] = self.paginator.page.number 
     data['countPage'] = self.paginator.page.paginator._count 
     serializer=ClientsCategorySerializer(categoryObjs,many=True) 
     data['result']=serializer.data 
     return Response({'data':data,'success':'1','detail':u'获得客户列表成功'}) 
    def categoryKeyList(self,albums,albumObjs): 
     for i in albums: 
      albumObjs={} 
      albumObjs['album_name']=i[0] 
      track=[] 
      albumObj['track']=track 
      albumObjs.append(albumObj) 

następnie u może dostanie odpowiedź:

{ 
    data[ 
    { 
      'album_name': 'The Grey Album', 
      'tracks': [ 
        {'order': 1, 'title': 'Public Service Annoucement'}, 
        {'order': 2, 'title': 'What More Can I Say'}, 
        {'order': 3, 'title': 'Encore'}, 
         ... 

     }, 
     {'album_name': 'The John Album', 
      'tracks': [ 
        {'order': 1, 'title': 'Public Annoucement'}, 
        {'order': 2, 'title': 'What sd Can I Say'}, 
        {'order': 3, 'title': 'sd'}, 
         ... 
}, 
...... 
} 
Powiązane problemy