简体   繁体   中英

How to save a ModelSerializer with a foreign Key in Django Rest Framework

I have these serializers

class OwnerSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = [
            'id',
            'name'
        ]


class PetSerializer(serializers.ModelSerializer):
    owner = OwnerSerializer(many=False, read_only=False)

    class Meta:
        model = Pet
        fields = [
            'id',
            'name',
            'owner'
        ]

    def create(self, validated_data):
        """
        Create and return a new `Pet` instance, given the validated data.
        """
        owner_data = validated_data.pop('owner', None)
        if owner_data:
            owner = User.objects.get(**owner_data)
            validated_data['owner'] = owner
        return Pet.objects.create(**validated_data)

This is my ViewSet :

class PetViewSet(viewsets.ModelViewSet):
    """
    ModelViewSet for model pets
    """
    queryset = Pet.objects.all()
    serializer_class = PetSerializer

    def create(self, request, *args, **kwargs):
        request.data['owner'] = {'id': request.user.id, 'name': request.user.name}
        pet_serializer = self.get_serializer(data=request.data)
        pet_serializer.is_valid(raise_exception=True)
        self.perform_create(pet_serializer)
        headers = self.get_success_headers(pet_serializer.data)
        return Response(pet_serializer.data, status=status.HTTP_201_CREATED, headers=headers)

But when storing it, all the data is saved, but in the created function the owner object does not arrive, it is shown as 'owner': OrderedDict ()}

So when I return the saved object, I get it with the owner with the default id, although the user I get in the view is 'owner': {'id': 10, 'name': 'My name'}} ):

My Json Response :

{
    "id": 26,
    "name": "My pet",
    "owner": {
        "id": 1
    }
}

What am I doing wrong? Thank you

.get returns one item and if it matched more, It raises an expception.

owner = User.objects.get(**owner_data) , remove the trailing [0]

EDIT: Since this was not your problem, I'll tell you the problem

You're overriding create which have the validated_data , You assumed that the owner is validated but it may wrong. Do the same logic in a method named validate_owner(self, value) in which value is the value you passed for owner in the POST before it gets validated.

It looks to me like it's returning normalized data of the owner object, rather than the relation.

Instead of owner = OwnerSerializer() try something like: owner = PrimaryKeyRelatedField(queryset=Owner.objects.all())

I made the next changes in my Serializers ,the main changes was in the OwnerSerializer, 'cause the id was read only for default.

class OwnerSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = [
            'id',
            'name'
        ]
        extra_kwargs = {
            'id': {
                'read_only': False,
                'required': True
            }
        }


class PetSerializer(serializers.ModelSerializer):
    owner = OwnerSerializer(many=False, read_only=False)

    class Meta:
        model = Pet
        fields = [
            'id',
            'name',
            'owner'
        ]

    def create(self, validated_data):
        """
        Create and return a new `Pet` instance, given the validated data.
        """
        owner_data = validated_data.pop('owner', None)
        if owner_data:
            owner = User.objects.get(**owner_data)
            validated_data['owner'] = owner
        return Pet.objects.create(**validated_data)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM