Динамические вложенные сериализаторы: пустые validated_data - PullRequest
0 голосов
/ 19 апреля 2019

Привет всем!

Итак, для начала рассмотрим поведение одной из конечных точек, над которой я работаю:

# 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"
}

Как видите, запросы POST и GET имеют некоторые поля, такие как read_only (статус, результаты, события), а вложенные поля требуют только поля "имя", но не все.

Вот сериализаторы для этой конечной точки:

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`

Итак, со всей следующей строкой я получаю 0 результат template = Templates.objects.filter(name=validated_data.pop('template')).first() Шаблон существует. Если я заменю validated_data.pop('template') на жестко закодированное имя, оно вернет объект. Но на данный момент он возвращает None. Потому что validated_data.pop('template') пусто ... Я не уверен почему, но я думаю, что это связано с тем, что я динамически изменяю поля. Я не хотел создавать 2 разных сериализатора (один для почтовых запросов и один для запросов на получение). Положить некоторые поля как read_only и динамически изменять поля было хорошим выбором здесь? Что ты думаешь?

Шаблоны и группы - это сериализаторы, которые вызывают проблемы здесь. Я не поставил сериализатор как ReadOnly. Я не понимаю, почему это не подтверждается ... Любое понимание этого?

Я думаю, что эта проблема также связана с этим: Django Rest Framework: поля динамической модели вложенного сериализатора

ПРОГРЕСС : Насколько я отлаживал, эта функция возвращает пустой список ... Вот почему это никогда не подтверждается ... Поэтому, поэтому не в конце списка ...

@cached_property
    def _writable_fields(self):
        return [
            field for field in self.fields.values() if not field.read_only
        ]

Еще раз спасибо!

С уважением,

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...