Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Manually combine multiple Django QuerySets, and serialize result using DRF

Tags:

django

I have been researching this for a couple days. Unfortunately, all of the proposed solutions I have found so far don't exactly work for me.

I am looking to manually combine two Django QuerySets into a single Django model, which I then want to serialize using a Django Rest Framework serializer. I then use the serializer for outputting JSON.

I have found various solutions on SO suggesting the use of itertools and chain, but it is unclear then how to serialize the result of chain.

Note that my goal here is for web application performance purposes. Each QuerySet works fine independently, but it requires two separate Ajax calls to retrieve the results. I would prefer to make only one Ajax call, manually combine the results on the server-side, then return the combined JSON.

This SO answer is close, but I can't figure out how to serialize the result of a chain, using DRF serializers.

like image 296
John Cleveland Avatar asked Sep 16 '16 17:09

John Cleveland


People also ask

How do I merge two QuerySets in Django?

You can also use the chain() method from the Itertools module, which allows you to combine two or more QuerySets from different models through concatenation. Alternatively, you can use union() to combine two or more QuerySets from different models, passing all=TRUE if you want to allow duplicates.

How do you combine two sets of queries?

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 serialization and Deserialization in DRF?

Serialization and Deserialization The first thing we need for our API is to provide a way to serialize model instances into representations. Serialization is the process of making a streamable representation of the data which we can transfer over the network. Deserialization is its reverse process.

Is serialization necessary in Django?

It is not necessary to use a serializer. You can do what you would like to achieve in a view. However, serializers help you a lot. If you don't want to use serializer, you can inherit APIView at a function-based-view.


1 Answers

After a couple more days of Googling for answers to this problem, I finally stumbled on this page which explains how to do pretty much what I wanted to do. I have posted my own answer here in case someone else has the same problem.

The technique seems simple enough now that I understand it, but I had a hard time finding anything online describing this technique. Basically, you chain together multiple querysets, then convert the chain to a Python list. Then iterate the list, manually calling the correct serializer, and appending to a dictionary. Then you can dump the dictionary to JSON.

I have posted the relevant code in case that link goes dead:

    def get_queryset(self):
        queryset_a = Post.objects.all()
        queryset_b = FriendRequest.objects.filter(is_unanswered=True)

        # Create an iterator for the querysets and turn it into a list.
        results_list = list(chain(queryset_a, queryset_b))

        # Optionally filter based on date, score, etc.
        sorted_list = sorted(results_list, key=lambda instance: -instance.date_created)

        # Build the list with items based on the FeedItemSerializer fields
        results = list()
        for entry in sorted_list:
            item_type = entry.__class__.__name__.lower()
            if isinstance(entry, Post):
                serializer = PostSerializer(entry)
            if isinstance(entry, FriendRequest):
                serializer = FriendRequestSerializer(entry)

            results.append({'item_type': item_type, 'data': serializer.data})

        return results
like image 89
John Cleveland Avatar answered Sep 29 '22 13:09

John Cleveland