Alfons Ingomar Alfons Ingomar - 7 months ago 46
Python Question

Make serializer for nested values in Django rest serializer

I am trying to integrate my django project with the api from mailchimp, to add users to a list I need to generate some json in the following format:

{
"email_address": "EMAIL",
"status": "subscribed",
"merge_fields": {
"FNAME": "FIRST_NAME",
"LNAME": "SURNAME"
},


Sadly I am having some struggles with the nested merge_field. I expected the following to work:

class MergeSerializer(serializers.Serializer):
FNAME = serializers.SerializerMethodField('get_first_name')
LNAME = serializers.SerializerMethodField('get_surname')

def get_first_name(self, obj):
return obj.first_name

def get_surname(self, obj):
return obj.surname

class CreateContactSerializer(serializers.Serializer):
email_address = serializers.EmailField()
status = serializers.SerializerMethodField('get_alternative_status')
merge_fields = MergeSerializer(read_only=True)

def get_alternative_status(self, obj):
return "subscribed"


This only generates some json with the email_address and the status, and completely ignores the merge_fields. After hours I have absolutely no clue what to try next. Does anybody know how to solve this problem?

Since I thought that the documentation for the marshmallow framework was a bit clearer I also tried it with their package, this however returend exactly the same result (so ignoring my merge_fields):

class MergeFieldsSchema(Schema):
FNAME = fields.String(attribute="first_name")
LNAME = fields.String(attribute="surname")


class CreateContactSerializer(Schema):
merge_fields = fields.Nested(MergeFieldsSchema)
email_address = fields.String()
status = fields.Constant("subscribed")

Answer

You don't say this, but I am assuming that surname and first_name are also part of the same object as email_address on your model, which is why the nested serializer does not work (as nested serializers are for foreign keys). If this is not the case, please add the model to the OP.

Because you just want to customize the output, you can use a Serializer Method on your main CreateContactSerializer:

class CreateContactSerializer(serializers.Serializer):
    email_address = serializers.EmailField()
    status = serializers.SerializerMethodField('get_alternative_status')
    merge_fields = serializers.SerializerMethodField('get_merge_fields')

    def get_alternative_status(self, obj):
        return "subscribed"

    def get_merge_fields(self, obj):
        return {
            "FNAME": obj.first_name,
            "LNAME": obj.surname
        }

If you want, you could even reuse the serializer that you already used and do

def get_merge_fields(self, obj):
    serializer = MergeSerializer(obj)
    return serializer.data;

Don't forget to add merge_fields to your fields

Comments