问题
Hello everyone !
So to start here is the behavior on one of the endpoint, I am working on:
# GET Request
{
"id": 1,
"name": "test",
"created_date": "date",
"completed_date": "date",
"template": { "name" : "test" }, => nested serializers with only the field "name"
"status": 1,
"results": [ { __all__ }, ... ], => nested serializers with all the fields
"groups": [ { "name" }, ... ], => nested serializers with only the field "name"
}
# POST Request
{
"name": "test",
"template": {"name":"test"}, => nested serializers with only the field "name"
"groups": [ {"name":"test"} ], => nested serializers with only the field "name"
}
As you can see, the POST and GET request have some of the field as read_only (status, results, events) and nested fields only require the "name" field not all of them.
Here is the Serializers for this endpoint:
class CampaignsSerializer(serializers.ModelSerializer):
template = TemplatesSerializer(fields=('name'))
results = ResultsSerializer(many=True, read_only=True)
groups = GroupsSerializer(many=True, fields=('name'))
class Meta:
model = Campaigns
fields = ('id', 'user_id', 'name', 'created_date', 'completed_date', 'template', 'status', 'results', 'groups', )
read_only_fields = ('status', 'results', )
def create(self, validated_data):
user = None
request = self.context.get("request")
if request and hasattr(request, "user"):
user = request.user
template = Templates.objects.filter(name=validated_data.pop('template')).first()
groups = validated_data.pop('groups')
campaign = Campaigns.objects.create(user_id=user.id,
template=template.id,
**validated_data)
for group in groups:
obj = Groups.objects.filter(**group)
campaign.groups.add(obj)
return campaign
class TemplatesSerializer(serializers.ModelSerializer):
class Meta:
model = Templates
fields = '__all__'
def __init__(self, *args, **kwargs):
fields = kwargs.pop('fields', None)
super(TemplatesSerializer, self).__init__(*args, **kwargs)
if fields is not None:
allowed = set(fields)
existing = set(self.fields)
for field_name in existing - allowed:
self.fields.pop(field_name)
Same thing for `GroupsSerializer`
So with all this, the following line gives me 0 result template = Templates.objects.filter(name=validated_data.pop('template')).first()
A template does exists. If I replace validated_data.pop('template')
with a hardcoded name it does return an object. But as of right now, it returns None
.
Because, validated_data.pop('template')
is empty... I am not sure why, But I think it's related to the fact that I am dynamically modifying fields. I didn't want to create 2 different serializers (one for post requests and one for get requests). Putting some fields as read_only, and dynamically modifying fields was the good choice here ? What do you think ?
Templates and Groups are the serializers that are causing trouble here. I didn't put the serializer as ReadOnly. I don't see why it's not getting validated... Any insight on this ?
I think this issue is related to this one too: Django Rest Framework : Nested Serializer Dynamic Model Fields
PROGRESS: As far as I debugged, this function returns an empty list... Which is why it's never getting validated... So therefore not at the end list...
@cached_property
def _writable_fields(self):
return [
field for field in self.fields.values() if not field.read_only
]
Thanks again !
Regards,
来源:https://stackoverflow.com/questions/55759817/dynamic-nested-serializers-empty-validated-data