Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework combine multiple querysets in one api endpoint

How can I connect the output of lists of a particular model, whose instances are filtered by different fields? For example, I have an Places model and two different url. In one, the entire list is displayed, and in the other only the instances with new_place = True. Do an API using django-filter.

models.py

class Places(models.Model):
    main_photo = models.ImageField(upload_to = 'album/')
    place = models.CharField(max_length=100)
    new_place = models.BooleanField(default = True)
    editor_choice = models.BooleanField(default = False, verbose_name = "Editors choice")
    most_popular = models.BooleanField(default = False, verbose_name = "Most popular")

serializer.py

class PlaceSerializer(ModelSerializer):
        
    url = HyperlinkedIdentityField(
    view_name='places_api:detail',
    lookup_field='pk'
    )
    class Meta:
        model = Places
        fields = (
            'url',
            'id',
            'main_photo',
            'name',
            'new_place',
            'most_popular', 
            'editor_choice',                        
        )

full_list_views.py

class PlacesListAPIView(ListAPIView):
    queryset = Places.objects.all()
    serializer_class = PlaceSerializer

new_places_views.py

class PlacesNewListAPIView(ListAPIView):
    queryset = Places.objects.all()
    serializer_class = PlaceSerializer
    filter_backends = (DjangoFilterBackend,)
    filter_fields = ('new_place',)

urls.py

url(r'^new/$', views.PlacesNewListAPIView.as_view(), name = 'list_new'),
url(r'^$', views.PlacesListAPIView.as_view(), name = 'place_list'),

This all works well on different urls. But what should I do to get both lists on one page. List of NEW at the top and full list at the bottom of the page?

like image 720
Jekson Avatar asked May 08 '18 17:05

Jekson


People also ask

How do I merge two Querysets in Django?

Use union operator for queryset | to take union of two queryset. If both queryset belongs to same model / single model than it is possible to combine querysets by using union operator. One other way to achieve combine operation between two queryset is to use itertools chain function.

What is mixin in Django REST framework?

mixins are classes that generally inherit from object (unless you are django core developer) mixins are narrow in scope as in they have single responsibility. They do one thing and do it really well. mixins provide plug-in functionality. although mixins work through inheritence, they DONT create a subtyping relation.

Can we use Django for REST API?

Django REST framework (DRF) is a powerful and flexible toolkit for building Web APIs. Its main benefit is that it makes serialization much easier. Django REST framework is based on Django's class-based views, so it's an excellent option if you're familiar with Django.

When should I use REST API Django?

Django REST framework is a powerful and flexible toolkit for building Web APIs. Some reasons you might want to use REST framework: The Web browsable API is a huge usability win for your developers. Authentication policies including packages for OAuth1a and OAuth2.


1 Answers

You could do something like this. Using QuerySet.union() to merge several querysets.

This example does not support pagination. I suspect that you would have to write a custom pagination class if you need pagination.

class MultiFilterPlacesListView(ListAPIView):
     """Custom queryset api view. Does not implement pagination"""

     pagination_class = None
     queryset = Places.objects.all()
     slice_size = 10  # count limit for each of the source queries

     def get_queryset(self):
         """Combine queries from new, editor choice and popular"""
         new_qs = self.queryset.filter(new_place=True)[:self.slice_size]
         editor_qs = self.queryset.filter(editor_choice=True)[:self.slice_size]
         popular_qs = self.queryset.filter(popular=True)[:self.slice_size]

         return new_qs.union(editor_qs, popular_qs, all=True)
like image 108
Håken Lid Avatar answered Dec 01 '22 00:12

Håken Lid