Django REST Framework: list of different serizalized objects?
Asked Answered
M

3

5

I have three different types of objects: RawArticle, RawPatent and RawGrant.

I have great working serializers, whose base class is serializers.ModelSerializer.

If I retrieve a query set of RawArticle I can pass that directly to the serializer with many=True and the output is nominal:

[{"save_link": "...", "published": "2014-01-18T20:39:54.086Z", }, {"save_link": "...", "published": "..."}, ...]

This response is generated from the following code:

return Response(RawArticleSerializer(articles, many=True).data)

Now that I have three different objects, I'd like to chain them just as above but with their respective objects.

I have been unsuccessful so far. My initial idea was to simply create a list of the serialized objects and return that (serialized of course), as such:

    all_latest = user_latest(request)['latest_articles']

    available_serializers = {RawArticle: RawArticleSerializer, RawGrant: RawGrantSerializer, RawPatent: RawPatentSerializer}
    serialized = []
    for article in all_latest:
        serialized.append((available_serializers[type(article)](article, many=False)).data)

    return Response(str(serialized))

The above code does not return JSON and the date time aren't converted to actual date and time as string.

My latest attempt was using json.dumps and simplejson and both raise a TypeError saying:

date time object is not serializable.

Any hint would be greatly appreciated.

Madai answered 20/1, 2014 at 13:27 Comment(0)
M
3

Sunny's answer will return JSON as a string (surrounded by double quotes). In order to avoid this, returning the list does what I needed:

    serialized = []
    AVAILABLE_SERIALIZERS = {RawArticle: RawArticleSerializer, RawGrant: RawGrantSerializer, RawPatent: RawPatentSerializer}
    for article in articles:
        serialized.append((AVAILABLE_SERIALIZERS[type(article)](article, many=False)).data)

    return Response(serialized)
Madai answered 22/1, 2014 at 13:12 Comment(0)
G
4

Personally, to deal with serializers, I create a serialize method in my models. This method in turn calls the appropriate code to serialize the data.

In this case, the code would look like:

class RawArticle(models.Model):
   def serialize(self):
       return RawArticleSerializer(self, many=False).data

Then, in your main code:

from rest_framework.renderers import JSONRenderer

all_latest = user_latest(request)['latest_articles']

serialized = [article.serialize() for article in all_latest]
return Response(JSONRenderer().render(serialized))

Even if the objects are not models, this approach should still work.

Grettagreuze answered 20/1, 2014 at 14:50 Comment(2)
Actually this returns a string. Returning a list after .data did the trick, as I'll explain in my answer below.Madai
Lack of good practice here: separe the serialization login from the business entities. I suggested approach with just: serialized = [RawArticleSerializer(article, many=False).data for article in all_latest] and remove the serialize() method from the RawArticle classSchechter
M
3

Sunny's answer will return JSON as a string (surrounded by double quotes). In order to avoid this, returning the list does what I needed:

    serialized = []
    AVAILABLE_SERIALIZERS = {RawArticle: RawArticleSerializer, RawGrant: RawGrantSerializer, RawPatent: RawPatentSerializer}
    for article in articles:
        serialized.append((AVAILABLE_SERIALIZERS[type(article)](article, many=False)).data)

    return Response(serialized)
Madai answered 22/1, 2014 at 13:12 Comment(0)
C
0

Think My Reminder class has a list of Expenses object. and the obj.get("expenses") is a list like below:

obj["expenses"] = [
    {
        "_id": "63facfbf8c4043821",
        "description": "some text",
        "value": 1,
        "date": "2023-02-26T02:40:25.658000Z"
    },
    {
        "_id": "63faffbf8c8f8aa25",
        "description": "222",
        "value": 22222,
        "date": "2023-02-26T02:40:37.965000Z"
    }
]

Define a class in you serializers file for Expenses. Have the Reminder class a method field for expenses like:

class ReminderSerializer(serializers.Serializer):
    expenses = serializers.SerializerMethodField()

    def get_expenses(self, obj):
        return ExpenseSerializer(obj.get("expenses"), many=True).data


And you're done!

Comedo answered 13/11, 2023 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.