[Answer]-REST Framework: POST a FK, get inline model back

1👍

With the below snippet, you can serialize the PK value into required data and while saving you can give only PK value

from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.utils.encoding import smart_text
from rest_framework import serializers

class CustomRelatedField(serializers.RelatedField):
    """
    Represents a primary key relationship with {'pk':1,'name': 'foo'}
    """
    read_only = False

    default_error_messages = {
        'does_not_exist': ("Invalid pk '%s' - object does not exist."),
        'incorrect_type': ('Incorrect type.  Expected {"id": 1} format , received %s.'),
    }

    def __init__(self, *args, **kwargs):
        self.fields = kwargs.pop('fields', ('id',))
        return super(CustomRelatedField, self).__init__(*args, **kwargs)


    def to_native(self, obj):
        data = {'id':obj.pk}
        for field in self.fields:
            value = getattr(obj, field)
            data[field] = value
        return data

    def from_native(self, data):
        if isinstance(data, int):
            data = {'id':data}
        if not isinstance(data, dict):
            received = type(data).__name__
            msg = self.error_messages['incorrect_type'] % received
            raise ValidationError(msg)
        if self.queryset is None:
            raise Exception('Writable related fields must include a `queryset` argument')

        try:
            return self.queryset.get(pk=data.get('id'))
        except ObjectDoesNotExist:
            msg = self.error_messages['does_not_exist'] % smart_text(data)
            raise ValidationError(msg)
        except (TypeError, ValueError):
            received = type(data).__name__
            msg = self.error_messages['incorrect_type'] % received
            raise ValidationError(msg)

and

class FooSerializer(serializers.ModelSerializer):
    bar = CustomRelatedField(fields=('id','name', 'number'))

    class Meta:
        model = Foo
        fields = ("name", "bar")

Leave a comment