Необязательный аргумент pk для CREATE в DRF ModelViewSet Джанго - PullRequest
0 голосов
/ 22 ноября 2018

У меня есть обычный ModelViewSet для одной из моих моделей, но я хочу иметь возможность указать конкретный ПК для создания нового экземпляра.Например, если бы я отправил:

{
    "name": "Name"
}

Было бы получить случайный pk.Но если я отправлю:

{
    "id": "123",
    "name": "Name"
}

Я хочу, чтобы у него был указанный pk (id).

Подобно этому человеку, что я сделал, это добавил *Поле 1011 * для моего ModelSerializer выглядит следующим образом:

class ConversationViewSet(viewsets.ModelViewSet):
    """
    List all conversations, or create new / edit existing product.
    """
    queryset = Conversation.objects.all()
    serializer_class = ConversationSerializer

class ConversationSerializer(serializers.ModelSerializer):
    id = serializers.CharField(required=False)  # Instead of serializer.ReadOnlyField()

    class Meta:
        model = Conversation
        fields = '__all__'

Хотя это работает для метода create, оно вызывает проблемы для update и partial_update, где id теперь требуетсяаргумент в качестве параметра строки запроса и в теле запроса, подобном этому (из документов):

update
PUT /conversations/{id}/
Update existing conversation.

Path Parameters
The following parameters should be included in the URL path.

Parameter       Description
id (required)   A unique value identifying this conversation.

Request Body
The request body should be a "application/json" encoded object, containing the following items.

Parameter       Description
id  
access_token    
username    
password    
app_user_id 
name    

Использование двух параметров с одинаковым именем, конечно, является плохой практикой.Например, при использовании requests и передаче словаря параметров он больше не работает, потому что не знает, к какому параметру я обращаюсь.

Как я могу это исправить так, чтобы параметр id былнеобязательно только для метода create, но все остальные методы (list, read, ...) остаются такими же, как в случае по умолчанию?

Мое решение

, основываясь на ответе JPG, я изменил свой сериализатор так:

class ConversationSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.context['view'].action == 'create':
            self.fields['id'] = serializers.CharField(required=False)

    class Meta:
        model = Conversation
        fields = '__all__'

1 Ответ

0 голосов
/ 22 ноября 2018

Я думаю, что это возможно путем переопределения метода сериализатора __init__().

class ConversationSerializer(serializers.ModelSerializer):
    <b>def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        if self.context['view'].action == 'create':
            self.fields['id'] = serializers.CharField()
        else:
            self.fields['id'] = serializer.ReadOnlyField()</b>

    class Meta:
        model = Conversation
        fields = '__all__'
...