Django остальные фреймворки записываемые вложенные данные сериализатора отсутствуют в validated_data - PullRequest
0 голосов
/ 05 сентября 2018

Я пытаюсь создать доступный для записи вложенный сериализатор для моей конечной точки API, однако при входе в метод родительского сериализатора create вложенные данные не появляются в моем validated_data словаре, как это предполагается в примере здесь . Вместо этого вложенный ключ даже не присутствует в словаре. Вместо этого это выглядит так: {'foo': 'bar'}. Таким образом, вложенные ключи выглядят плоскими, а любые другие вложенные объекты с такими же ключами перезаписываются.

Есть какие-нибудь подсказки, в чем может быть проблема? У меня есть довольно сложная логика проверки, однако после обрезки всего этого проблема не была исправлена, поэтому она кажется неактуальной.

Мои модели определены так:

class Payment(models.Model):
    id = models.AutoField(primary_key=True)
    foo = models.CharField(max_length=15, blank=True, null=True)

class Booking(models.Model):
    id = models.AutoField(primary_key=True)
    payment = models.ForeignKey(Payment, blank=True, null=True)

Мои сериализаторы:

class PaymentSerializer(serializers.ModelSerializer):
    class Meta:
        model = Payment
        fields = '__all__'

class BookingSerializer(serializers.ModelSerializer):
    payment = PaymentSerializer(source='*', write_only=True)

    def create(self, validated_data):
        print("Creating booking", validated_data) # Outputs "Creating booking {'foo': 'bar'}"
        payment_data = validated_data.pop('payment') # Obviously errors at this point
        primary_guest = Payment.objects.create(payment_data)
        booking = Booking.objects.create(**validated_data)
        # other creation related code

        return booking

    class Meta:
        fields = '__all__'

My ViewSet:

class PrebookingViewSet(viewsets.ModelViewSet):
    queryset = Booking.objects.all().order_by('id')
    serializer_class = BookingSerializer

Мой запрос содержит следующее тело сообщения:

{
    "payment": {
        "foo": "bar"
    }
}

Ответы [ 2 ]

0 голосов
/ 05 сентября 2018

Похоже, что после всех устраненных неисправностей я наткнулся на решение проблемы более или менее, придумывая пример, чтобы поделиться своим вопросом. Это хорошее упражнение. Проблема была вызвана определением моего вложенного сериализатора.

Вместо:

payment = PaymentSerializer(source='*', write_only=True)

Мне нужно было:

payment = PaymentSerializer(write_only=True)

Мой validated_data словарь теперь содержит вложенный словарь под ключом платежа.

Я не уверен, почему я включил это, я думаю, что я использовал это в другом месте, чтобы развернуть поля во вложенном представлении. Кажется, я не могу найти никакой документации о том, как это должно работать, и почему это вызвало поведение, которое я видел здесь. Любые комментарии по этому поводу приветствуются!

0 голосов
/ 05 сентября 2018

То, что вы определили как source='*',.

От Сериализатор DRF Doc

Значение source='*' имеет особое значение и используется для указания того, что весь объект должен быть передан в поле. Это может быть полезно для создания вложенных представлений или для полей, которым требуется доступ ко всему объекту для определения выходного представления

То есть ваша полезная нагрузка {"payment": {"foo": "bar"}} перейдет в PaymentSerializer вместо {"foo": "bar"}


Решение
Просто удалите source='*';)

class BookingSerializer(serializers.ModelSerializer):
    <b>payment = PaymentSerializer(write_only=True)</b>

    def create(self, validated_data):
        # your code
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...