Wednesday, 5 October 2022

Best architecture for dynamically validating and saving field

I am looking for the good architecture for my problem. I am using django rest framework for building an API. I receive a list of dict which contains an id and a list of values. The list of values need to be validated according to the id.

Example of my code:

class AttributesSerializer(serializers.Serializer):
    id = serializers.PrimaryKeyRelatedField(queryset=Attribute.objects.all(), source="attribute", required=True)
    values = serializers.ListField()
    
    def validate(self, validated_data):
        attribute = validated_data["attribute"]
        values = validated_data["values"]
        
        # This function returns the corresponding field according to attribute
        values_child_field = get_values_field(attribute)
        self.fields["values"].child = values_child_fields
        new_values = self.fields["values"].run_child_validation(values)
        
        set_value(validated_data, "values", new_values)

        return validated_data


class SerializerExample(serializers.Serializer):
    attributes = AttributesSerializer(many=True)

I want to parse json like this:

{
    "attributes": [
        {"id": 124, "values": ["value"]},
        {"id": 321, "values": [42]},
        {
             "id": 18,
             "values": [
                 {
                     "location": {"type": "Point", "geometry": {...}},
                     "address": "an address",
                 }
             ],
        },
    ]
}

Currently, this code does not work. DRF seems to try to revalidate all values entries for each iteration with each child field. I do not understand why... I guess I could make it work without using this fields["values"] for making the validation and just retrieve the field and use it directly, but i need this field for making the save later.

Do you think my architecture is ok? What is the good way for parsing this type of data with DRF?

EDIT:

Structure of models are complex but a version simplified following:

class Attribute(models.Model):

    class DataType(models.TextChoices):
        TEXT = "TEXT", _("datatype_text")
        INTEGER = "INTEGER", _("datatype_integer")
        DATETIME = "DATETIME", _("datatype_datetime")
        BOOL = "BOOL", _("datatype_bool")
        # Some examples, but there are about 30 items with 
        # type very complicated like RecurrenceRule (RFC2445) 
        # or GeoJSON type


    label = models.CharField()
    category = models.ForeignKey(Category)
    attribute_type = models.CharField(choices=DataType.choices)


class AttributeValue(models.Model):
    attribute = models.ForeignKey(Attribute)
    # a model which represents an object with list of attributes
    baseobject = models.ForeignKey(BaseObject)
    value = models.TextField()

AttributeValue is like a through table for manytomany relation between BaseObject model and Attribute model. My JSON represents the list of attribute/values attached to a baseobject.

In fact I don't understand why DRf doesn't allow delegating registration in the child serializers of the parent serializer. This would allow much greater flexibility in code architecture and separation of responsibilities.



from Best architecture for dynamically validating and saving field

No comments:

Post a Comment