[Django] 25 - DRF: Pagination and Filtering
实现图片等其他资源的逐步加载。
Django Rest Framework for beginners
17 videos
Last updated on Jul 20, 2021
Pagination
Ref: API Pagination. Django Rest Framework complete tutorial.#13
queryset.filter
-
Old
def get_queryset(self): """Retrieve albums for authenticated user."""
return self.queryset.filter(user=self.request.user).order_by('-id')
- New
def _params_to_ints(self, qs): """Convert a list of strings to integers.""" return [int(str_id) for str_id in qs.split(',')]
def get_queryset(self): """Retrieve recipes for authenticated user."""
# ----------------------------------------------------------------- tags = self.request.query_params.get('tags') ingredients = self.request.query_params.get('ingredients')
queryset = self.queryset
if tags: tag_ids = self._params_to_ints(tags) queryset = queryset.filter(tags__id__in=tag_ids) # <----
if ingredients: ingredient_ids = self._params_to_ints(ingredients) queryset = queryset.filter(ingredients__id__in=ingredient_ids) # <---- # ----------------------------------------------------------------- return queryset.filter( user=self.request.user ).order_by('-id').distinct()
Implement tag and ingredient filtering
- app/dataset/tests/test_photos_api.py
+ def test_filter_photos_assigned_to_albums(self): + """Test listing photos to those assigned to albums."""
+ + in1 = Photo.objects.create(user=self.user, name='Apples') + in2 = Photo.objects.create(user=self.user, name='Turkey') + album = Album.objects.create( + title='Apple Crumble', + time_minutes=5, + price=Decimal('4.50'), + user=self.user, + ) + album.photos.add(in1) + + res = self.client.get(PHOTOS_URL, {'assigned_only': 1}) + + s1 = PhotoSerializer(in1) + s2 = PhotoSerializer(in2) + self.assertIn(s1.data, res.data) + self.assertNotIn(s2.data, res.data) + + def test_filtered_photos_unique(self): + """Test filtered photos returns a unique list."""
+ + ing = Photo.objects.create(user=self.user, name='Eggs') + xxx = Photo.objects.create(user=self.user, name='Lentils') + album1 = Album.objects.create( + title='Eggs Benedict', + time_minutes=60, + price=Decimal('7.00'), + user=self.user, + ) + album2 = Album.objects.create( + title='Herb Eggs', + time_minutes=20, + price=Decimal('4.00'), + user=self.user, + ) + album1.photos.add(ing) + album2.photos.add(ing) + + res = self.client.get(PHOTOS_URL, {'assigned_only': 1}) + + self.assertEqual(len(res.data), 1)
- app/dataset/tests/test_tags_api.py
+ def test_filter_tags_assigned_to_albums(self): + """Test listing tags to those assigned to albums."""
+ + tag1 = Tag.objects.create(user=self.user, name='Breakfast') + tag2 = Tag.objects.create(user=self.user, name='Lunch') + album = Album.objects.create( + title='Green Eggs on Toast', + time_minutes=10, + price=Decimal('2.50'), + user=self.user, + ) + album.tags.add(tag1) + + res = self.client.get(TAGS_URL, {'assigned_only': 1}) + + s1 = TagSerializer(tag1) + s2 = TagSerializer(tag2) + self.assertIn(s1.data, res.data) + self.assertNotIn(s2.data, res.data) + + def test_filtered_tags_unique(self): + """Test filtered tags returns a unique list."""
+ + tag = Tag.objects.create(user=self.user, name='Breakfast') + xxx = Tag.objects.create(user=self.user, name='Dinner') + album1 = Album.objects.create( + title='Pancakes', + time_minutes=5, + price=Decimal('5.00'), + user=self.user, + ) + album2 = Album.objects.create( + title='Porridge', + time_minutes=3, + price=Decimal('2.00'), + user=self.user, + ) + album1.tags.add(tag) + album2.tags.add(tag) + + res = self.client.get(TAGS_URL, {'assigned_only': 1}) + + self.assertEqual(len(res.data), 1)
- app/dataset/views.py
@extend_schema_view( list=extend_schema( parameters=[ OpenApiParameter( 'assigned_only', OpenApiTypes.INT, enum=[0, 1], description='Filter by items assigned to albums.', ), ] ) ) class BaseAlbumAttrViewSet(mixins.DestroyModelMixin, mixins.UpdateModelMixin, mixins.ListModelMixin, viewsets.GenericViewSet): """Base viewset for album attributes.""" authentication_classes = [TokenAuthentication] permission_classes = [IsAuthenticated] def get_queryset(self): """Filter queryset to authenticated user."""
assigned_only = bool( int(self.request.query_params.get('assigned_only', 0)) ) queryset = self.queryset if assigned_only: queryset = queryset.filter(album__isnull=False) return queryset.filter( user=self.request.user ).order_by('-name').distinct()
class TagViewSet(BaseAlbumAttrViewSet): """Manage tags in the database.""" serializer_class = serializers.TagSerializer queryset = Tag.objects.all() class PhotoViewSet(BaseAlbumAttrViewSet): """Manage photos in the database.""" serializer_class = serializers.PhotoSerializer queryset = Photo.objects.all()
End.