Операции создания / обновления с вложенными сериализаторами - PullRequest
0 голосов
/ 14 октября 2019

Я, как новичок в разработке Django, пытаюсь создать RESTful API для мобильного приложения. Я взял на себя существующий проект, и предыдущие разработчики использовали Django REST Framework. Супер классная упаковка, с которой легко работать. За исключением одной вещи ...

Эта проблема возникает, когда я хочу создать новые ресурсы, в которых есть вложенные сериализаторы. Я не очень хорошо объясняю проблемы программного обеспечения со словами, поэтому вот упрощенная версия моего случая:

class UserSerializer(serializers.ModelSerializer):
    company = CompanySerializer()
    # other props and functions are unrelated


class CompanySerializer(serializers.ModelSerializer):
    # props and functions are unrelated

Теперь с этой структурой конечные точки GET /users и GET /users/{id} работают отлично, и я получаюрезультаты я ожидаю. Но с POST /users и PATCH /users/{id} я получаю ответ, в котором говорится, что мне нужно предоставить объект для company проп, и он должен напоминать объект Company со всеми необходимыми реквизитами, чтобы он мог создаватькомпания тоже. И я уверен, что он пытается создать новую компанию, потому что я пытался отправить { company: { id: 1 } }, и он просто игнорирует идентификатор и требует name для создания новой. Это явно не то, что я хочу, потому что я просто хочу создать пользователя (который может принадлежать или не принадлежать компании), не как пользователя, так и компанию.

Я имеюпопытался переключить это CompanySerializer на serializers.PrimaryKeyRelatedField, и похоже, что оно работает на создании конечной точки, но теперь я не получаю объект Company в списке и подробных конечных точках.

Чего мне здесь не хватает? Я на 99% уверен, что они не собирались так работать.

Ответы [ 2 ]

0 голосов
/ 14 октября 2019

Вам необходимо переопределить методы create() и update() на вложенных сериализаторах, чтобы сделать их доступными для записи. В противном случае DRF не уверен, что делать с вложенными объектами. Самое простое переопределение будет выглядеть примерно так:

class UserSerializer(serializers.ModelSerializer):
    company = CompanySerializer()
    ...

    def create(self, validated_data):
        return User.objects.create(**validated_data)

    def update(self, instance, validated_data):
        user = instance
        user.__dict__.update(validated_data)
        user.save()
        return user

Примечание: не проверял этот вариант update(), возможно, потребуется корректировка.

0 голосов
/ 14 октября 2019

Хитрость заключается в том, чтобы использовать другой класс сериализатора для получения обновлений - один с PrimaryKeyRelatedField и один с вложенным сериализатором. Вы можете переопределить get_serializer_class, чтобы сделать это. Предполагая, что вы используете viewset:

class BaseUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = (...)

class WriteUserSerializer(BaseUserSerializer):
    company = CompanySerializer()

class ReadUserSerializer(BaseUserSerializer):
    company = PrimaryKeyRelatedField()

class UserViewSet(viewsets.ViewSet):
    def get_serializer_class(self):
        if self.action in ["create", "update", "partial_update", "destroy"]:
            return WriteUserSerializer
        else:
            return ReadUserSerializer
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...