Сериализатор Django Rest Framework create() не запускается

У меня есть следующий сериализатор

class MyModelSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    def create(self, validated_data):
        print("TEST")
        MyModel, created = MyModel.objects.get_or_create(**validated_data)
        return MyModel

    class Meta:
        model = MyModel
        fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'text',)

и следующий набор видов:

class MyModelViewSet(viewsets.ModelViewSet):
    queryset = MyModel.objects.all()
    serializer_class = MyModelSerializer

Когда я делаю запрос POST к конечной точке, соответствующей указанному набору представлений, метод create() абсолютно ничего не делает. Я попытался распечатать в консоли TEST, как видите, но ничего.

Кто-нибудь знает об этом странном поведении?

Заранее спасибо!

Изменить: вызов API:

return axios({
  method: 'post',
  url: 'http://localhost:8000/api/mymodel/',
  data: {
     title: this.title,
     movie: this.id,
     text: this.text,
     user: this.user
}

person yierstem    schedule 26.09.2018    source источник
comment
Возвращает ли он какой-либо ответ?   -  person JPG    schedule 26.09.2018
comment
Нет, с ним или без него, одно и то же.   -  person yierstem    schedule 26.09.2018
comment
Убедитесь, что отправляемые вами данные действительны (например, код ответа 200/201).   -  person Linovia    schedule 26.09.2018
comment
Когда я отправляю данные, я получаю 400 Bad request   -  person yierstem    schedule 26.09.2018
comment
Как вы вызываете API? Пожалуйста, добавьте этот фрагмент кода также @yierstem   -  person JPG    schedule 26.09.2018
comment
@JPG так же, как и в предыдущем посте, я немедленно отредактирую пост.   -  person yierstem    schedule 26.09.2018
comment
Выход: "user": { "username": ["A user with that username already exists." ]}   -  person yierstem    schedule 26.09.2018
comment
печатает ли он строку TEST в консоли?   -  person JPG    schedule 26.09.2018
comment
Нисколько. Он обрабатывает create() так, как будто его там не было.   -  person yierstem    schedule 26.09.2018
comment
Что происходит с этим решением?   -  person JPG    schedule 26.09.2018
comment
Это дает мне вывод сверху a user with that username already exists, извините за поздний ответ.   -  person yierstem    schedule 26.09.2018


Ответы (3)


Если вы посмотрите на реализацию обработки POST в ViewSet, вы увидите следующее:

def create(self, request, *args, **kwargs):
    serializer = self.get_serializer(data=request.data)
    serializer.is_valid(raise_exception=True)
    self.perform_create(serializer)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Ваш метод create вызывается после того, как сериализатор проверяет данные.

Ошибка, которую вы видите (пользователь уже существует), является результатом вызова serializer.is_valid из фрагмента выше.

Следовательно, он никогда не сможет вызвать ваш create. Ваше создание будет вызываться как часть self.perform_create() из этого фрагмента выше.

Так что это означает, что вы пытаетесь создать пользователя, который уже существует. Итак, в вашей модели у вас есть уникальное имя пользователя.

person Enthusiast Martin    schedule 27.09.2018
comment
Я просмотрел исходный код, я пришел к тому же выводу, но я не знаю, как мне это обойти, есть ли способ изменить данные сериализатора до того, как они будут проверены? Должен ли я изменить serializer.initial_data заранее? Спасибо - person yierstem; 27.09.2018
comment
@yierstem, почему ты хочешь это сделать? хорошей практикой является проверка данных. И вы должны сделать это в любом случае. Сериализатор не позволит вам вызывать save без предварительного вызова is_valid. если вы не хотите проверять данные и просто вызывать create, просто не используйте сериализатор вообще. - person Enthusiast Martin; 27.09.2018
comment
Я не хочу исключать проверку данных, я хочу изменить данные, которые передаются сериализатору. по какой-то причине он пытается создать запись пользователя, когда я просто хочу получить пользовательские данные для конкретного экземпляра сериализованной модели. Я хочу, чтобы он вел себя как обычные внешние ключи в Django, я отправляю пользовательский pk, представление получает пользовательский pk из запроса, чтобы получить необходимый пользовательский объект (а не создавать его), чтобы создать запись mymodel, чтобы я мог получить ее, когда Я отправляю запрос на получение mymodel viewset. - person yierstem; 27.09.2018
comment
Кажется, вы хотите сделать обновление тогда? поэтому вместо POST сделайте PUT/PATCH. это получит экземпляр и обновит поля, которые вы хотите - person Enthusiast Martin; 27.09.2018
comment
Я не уверен, зачем это поставить/исправление, если я хочу создать новые записи для моей модели и ничего не менять в пользователе, я не слежу. - person yierstem; 27.09.2018
comment
@yierstem, вы сказали это, я просто хочу получить пользовательские данные для определенного экземпляра .... получает пользовательский pk из запроса, чтобы получить необходимый пользовательский объект (а не создавать его) ... так что для меня это выглядит как обновление . - person Enthusiast Martin; 27.09.2018
comment
Да, но это должно быть представление создания, потому что у меня еще нет записи mymodels, поэтому у меня нет записи, созданной для ее обновления. Например, в сериализаторе mymodel у меня есть поле фильма, которое является внешним ключом, а также пользовательским полем, но по какой-то причине указание пользовательского поля в качестве сериализатора не сработает, он также пытается отправить данные в пользовательское поле. , чего я не хочу. Когда я отправляю запрос на публикацию, я заполняю поле фильма (которое, как я уже упоминал, является внешним ключом) pk этого существующего фильма. - person yierstem; 27.09.2018

Ok. Я нашел альтернативу. Поскольку мне нужно было только имя пользователя из пользовательского объекта, я удалил user = UserSerializer() и добавил user_username = serializers.ReadOnlyField(source='user.username'):

class ReviewSerializer(serializers.ModelSerializer):
    user_username = serializers.ReadOnlyField(source='user.username')

    class Meta:
        model = Review
        fields = ('pk', 'title', 'user', 'user_username', 'movie', 'timestamp', 'review_text',)

user = UserSerializer() вызвал у меня головную боль, поэтому я справился с этим. Я проверю ответ Entushiast Martin как решение, так как они привели меня к фактическому ответу. Спасибо.

Решено.

person yierstem    schedule 27.09.2018

Это может быть связано с тем, что у вас есть какая-то обработка ошибок, потому что то, как написана ваша функция создания def, вызовет ошибку. Я протестировал приведенный ниже код, и он сработал для меня, попробуйте:

class MyModelSerializer(serializers.ModelSerializer):
    user = UserSerializer()

    class Meta:
        model = MyModel
        fields = ('pk', 'title', 'user', 'movie', 'timestamp', 'text',)

    def create(self, validated_data):
        print("TEST")
        data = validated_data
        data, created = MyModel.objects.get_or_create(**data)
        return data

Надеюсь это поможет!

person Paul Tuckett    schedule 26.09.2018