tutorial - Paginación en Django REST Framework?
the django project (4)
Respuesta copiada del enlace de Tom arriba en caso de pudrición futura de bit:
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
Estamos utilizando Django REST Framework para nuestra API y tenemos la necesidad de paginar los campos de relación que devuelven varios elementos.
Para demostrar el uso de ejemplos similares a los de la documentación :
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'')
Ejemplo de salida serializada para un álbum:
{
''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''},
...
],
}
Esto se vuelve problemático cuando hay, por ejemplo, cientos de pistas en el álbum. ¿Hay alguna manera de paginar las ''pistas'' en este caso?
Idealmente, sé que en casos como este, las ''pistas'' deberían apuntar a una URL API que simplemente devuelve las pistas para un álbum en particular, que a su vez se puede paginar fácilmente. La desventaja de ese enfoque es la solicitud adicional (y por lo tanto demora, etc.) requerida para obtener incluso las primeras pistas. En nuestro caso, es importante que podamos obtener al menos algunas de las Pistas con la solicitud única a la API de Álbum y luego cargar dinámicamente el resto de las pistas cuando sea necesario.
¿Ofrece el DRF alguna característica o patrón específico para esto? ¿O hay algún problema?
Desde DRF 3.1, PaginationSerializer
no es compatible. Aquí hay una solución.
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
O puede sustituir def paginated_tracks
por
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
Incluso requiere una consulta menos que la anterior.
Creo una API en archivos de vista y obtengo una alerta de error " Exception Type: KeyError Exception Value:''request''"
. ¿Dónde estableciste la request
? Mi código 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
Los métodos de Malcolm Box y Deepak Prakash pueden ayudar a serializar los objetos relatológicos, pero tal como dijo @eugene anteriormente, solo funciona para un solo Alum. Para un Álbum podemos hacer esto:
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)
Entonces puede obtener la respuesta:
{
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''},
...
},
......
}