Showing extra field on ManyToMany relationship in Django serializer

Viewed 304

I have a ManyToMany field in Django, like this:

class Dictionary(models.Model):

    traditional = models.CharField(max_length=50)
    simplified = models.CharField(max_length=50)
    pinyin_numbers = models.CharField(max_length=50)
    pinyin_marks = models.CharField(max_length=50)
    translation = models.TextField()
    level = models.IntegerField()
    frequency = models.IntegerField()
    idiom = models.BooleanField()
    child_char = models.ManyToManyField('Dictionary', through='DictionaryChildChar', null=True)

    class Meta:
        db_table = 'dictionary'
        indexes = [
            models.Index(fields=['simplified', ]),
            models.Index(fields=['traditional', ]),
        ]

class DictionaryChildChar(models.Model):

    class Meta:
        db_table = 'dictionary_child_char'

    from_dictionary = models.ForeignKey(Dictionary, on_delete=models.CASCADE, related_name="from_dictionary")
    to_dictionary = models.ForeignKey(Dictionary, on_delete=models.CASCADE, related_name="to_dictionary")
    word_order = models.IntegerField()

Currently, I have a serializer like this:

class FuzzySerializer(serializers.ModelSerializer):
    pinyin = serializers.CharField(
        required=False, source="pinyin_marks")
    definition = serializers.CharField(
        required=False, source="translation")
    hsk = serializers.CharField(required=False, source="level")

    class Meta:
        model = Dictionary
        fields = ["id", "simplified", "pinyin", "pinyin_numbers","definition", "hsk", "traditional", "child_char"]
        depth = 1 

This gives me a dictionary entry, as well as the child dictionary entries associated with it (as a Chinese word is made up of several Chinese characters)

However, I need to know what order these child characters are in, and hence why I have word_order.

I would like this word_order field to appear on the individual child_char - how do I write my serializer in such a way that this additional field is present? Would I need to make a separate serializer for child_char?

EDIT: I have tried this serializer, it doesn't work:

class FuzzyChildCharSerializer(serializers.ModelSerializer):
    class Meta:
        model = DictionaryChildChar
        fields = ["word_order"]
2 Answers

Easiest way is to create a dedicated FuzzyChildCharSerializer and then connect it to your original serializer as a nested relationship:

class FuzzyChildCharSerializer():
    class Meta:
        model = DictionaryChildChar
        fields = ["word_order"] # And whatever other fields you want

class FuzzySerializer():
    child_char = FuzzyChildCharSerializer(many=True)
    ...

You could also write a SerializerMethodField.

It appears I had to bridge the connection via the glue table, which makes sense.

class FuzzyChildCharSerializer(serializers.ModelSerializer):
    pinyin = serializers.CharField(
        required=False, source="pinyin_marks")
    definition = serializers.CharField(
        required=False, source="translation")
    hsk = serializers.CharField(required=False, source="level")

    class Meta:
        model = Dictionary
        fields = ["id", "simplified", "pinyin", "pinyin_numbers","definition", "hsk", "traditional",]

class FuzzyChildCharSerializerGlue(serializers.ModelSerializer):
    to_dictionary = FuzzyChildCharSerializer()
    class Meta:
        model = DictionaryChildChar
        fields = '__all__'

class FuzzySerializer(serializers.ModelSerializer):
    pinyin = serializers.CharField(
        required=False, source="pinyin_marks")
    definition = serializers.CharField(
        required=False, source="translation")
    hsk = serializers.CharField(required=False, source="level")
    from_dictionary = FuzzyChildCharSerializerGlue(many=True)

    class Meta:
        model = Dictionary
        fields = ["id", "simplified", "pinyin", "pinyin_numbers","definition", "hsk", "traditional", "from_dictionary"]
        depth = 1

This provides each character with its given word order

Related