yezyilomo / django-restql

Turn your API made with Django REST Framework(DRF) into a GraphQL like API.
https://yezyilomo.github.io/django-restql
MIT License
618 stars 43 forks source link

Can not replace JSONField with a custom Serializer #275

Open dnievas04 opened 3 years ago

dnievas04 commented 3 years ago

I have the following serializer:

class ProductSerializer(NestedModelSerializer):
    persons = NestedField(PersonSerializer, required=True, many=True)
    attributes = serializers.JSONField()

but when I try to change the attributes field with a new serializer like this.

class ProductAttributesSerializer(serializers.Serializer):
    volume= serializers.FloatField(required=True)
    volume_units = serializers.FloatField(required=True)

class ProductSerializer(NestedModelSerializer):
    persons = NestedField(PersonSerializer, required=True, many=True)
    attributes = ProductAttributesSerializer(required=True)

I get an error when trying to create new objects.

I get the following error:

AssertionError at /api/v2/product/ The .create() method does not support writable nested fields by default. Write an explicit .create() method for serializer serializers.ProductSerializer, or setread_only=True` on nested serializer fields.

Any ideas on how can I could fix this? Thanks

yezyilomo commented 3 years ago

You should use NestedField on your attributes field too, like

class ProductSerializer(NestedModelSerializer):
    persons = NestedField(PersonSerializer, required=True, many=True)
    attributes = NestedField(ProductAttributesSerializer, required=True, many=True)
dnievas04 commented 3 years ago

Hey @yezyilomo thanks for your answer. I tried your example, but after declaring the field as a NestedField, I was asked to add the Meta attribute.

AttributeError: type object 'ProductAttributesSerializer' has no attribute 'Meta'

Remember that my serializer is trying to replace a JSONField, so it is not associated with any particular model. However for testing purposes I added the meta class like this:

class ProductAttributesSerializer(serializers.Serializer):
    volume_of_solution_prepared = serializers.FloatField(required=True)
    volume_units = serializers.FloatField(required=True)

    class Meta:
        fields = ('volume_of_solution_prepared', 'volume_units')

After trying to create a new object I got the following error again:

NotImplementedError at /api/v2/product/ create() must be implemented.

Any other ideas? I would appreciate any help! Thanks

yezyilomo commented 3 years ago

If attributes is not a nested field, why would you need to replace it with a serializer, I guess my question is when user pass product attributes (volume_of_solution_prepared, volume_units) what do you do with them, or where do they go? aren’t they associated with Product model?, What’s the relationship between Product and ProductAttributes on your models?