Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't assign related object in creation #138

Open
uripeled2 opened this issue Mar 26, 2021 · 1 comment
Open

Can't assign related object in creation #138

uripeled2 opened this issue Mar 26, 2021 · 1 comment

Comments

@uripeled2
Copy link

uripeled2 commented Mar 26, 2021

from django.db import models


class Location(models.Model):
    city = models.CharField(max_length=100)


class Store(models.Model):
    name = models.CharField(max_length=100)
    location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True)


class LocationSerializer(serializers.ModelSerializer):
         class Meta:
                 model = Location
                  fields = ('id', 'city')


class StoreSerializer(serializers.ModelSerializer):
    location = LocationSerializer(required=False, allow_null=True)
    
    class Meta:
        model = Store
       fields = ('id', 'name', 'location')



1. {
"name": "KFC",
"location": {"id": 1}
}

2. {
"name": "KFC",
"location": 1
}

The first request return:

{
    "location": {
            "city": [
                "This field is required."
        ]
    }
}

And the second raise TypeError: argument of type 'int' is not iterable

The first request works fine when I do patch/put

@smilerz
Copy link

smilerz commented Feb 21, 2024

I created an override for WritableNestedModelSerializer.to_internal_value() that I think is generalizable. This hasn't been exhaustively tested, so use at your own risk.

    def to_internal_value(self, data):
        def get_object(field, model, serializer, value):
            nested_obj = get_object_or_None(model, id=value)
            if nested_obj is not None:
                obj = serializer(nested_obj, context=self.context).data
                for key in list(serializer(nested_obj, context=self.context).data):
                    if key not in ['id'] + [field_name for field_name, field in serializer().fields.items() if field.required]:
                        obj.pop(key, None)
                return obj
            else:
                return value
        for f in list(data):
            if issubclass(self.fields[f].__class__, serializers.Serializer):
                if isinstance(data[f], int):
                    data[f] = get_object(f, self.fields[f].Meta.model, self.fields[f].__class__, data[f])
            elif issubclass(self.fields[f].__class__, serializers.ListSerializer):
                for idx, item in enumerate(data[f]):
                    if isinstance(item, int):
                        data[f][idx] = get_object(f, self.fields[f].child.Meta.model, self.fields[f].child.__class__, item)
        return super().to_internal_value(data)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants