DRF Установите OneToOneField для текущего вошедшего в систему пользователя - PullRequest
1 голос
/ 05 марта 2019

У меня есть модель, у которой OneToOneField выглядит следующим образом:

class Customer(models.Model):
    """A Class to represent a Customer in  System """

    user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)

Сериализатор для которого выглядит следующим образом:

class CustomerSerializer(serializers.ModelSerializer):
    """A Serizlier class for customer """

    class Meta:
        model = models.Customer
        fields = ('user', 'first_name', 'last_name', 'dob', 'gender') 

В настоящее время просматриваемый API показывает раскрывающийся список дляпользователь

enter image description here

как я могу установить user для текущего пользователя, вошедшего в систему в CustomerSerializer и сделать его доступным только для чтения?то есть поле не должно быть параметром, пригодным для передачи в конечную точку, и вместо этого должно быть полем только для чтения, соответствующим текущему зарегистрированному пользователю.

Ответы [ 3 ]

2 голосов
/ 06 марта 2019

Прежде всего, вы должны установить user в поле read_only.Таким образом, вы не сможете изменить значение из API .Это можно сделать, указав read_only=True в поле ИЛИ , добавив read_only_fields в метакласс сериализатора.

class CustomerSerializer(serializers.ModelSerializer):
    """A Serizlier class for customer """

    class Meta:
        model = models.Customer
        fields = ('user', 'first_name', 'last_name', 'dob', 'gender')
        <b>read_only_fields = ('user',)</b>


Таким образом, DRF не будет принимать входные данные для поля user из полезной нагрузки JSON, которую вы размещаете.


Тогда, как мы можем передать зарегистрированное пользовательское значение при Customer создании экземпляра?

Я предполагаю, что вы используете ModelViewset представление, чтобы оно прошло request объект и view объект для соответствующего сериализатора.В сериализаторе мы можем получить доступ к контекстным данным с помощью context переменной класса сериализатора.
Итак, переопределить create() метод CustomerSerializer как показано ниже (я добавляю полный конфиг нижеприведенного сериализатора)

class CustomerSerializer(serializers.ModelSerializer):
    """A Serizlier class for customer """

    class Meta:
        model = models.Customer
        fields = ('user', 'first_name', 'last_name', 'dob', 'gender')
        <b>read_only_fields = ('user',) # added <<<<

    def create(self, validated_data): # override this method <<<
        """
        Since the 'user' is a read_only field, the validated data doesn't contain it.
        """
        user = self.context['request'].user
        validated_data['user'] = user
        return super().create(validated_data)</b>
0 голосов
/ 06 марта 2019

Вы можете сделать это, переопределив get_fields (self) из CustomerSerializer . Проходящий текущий запрос пользователя и фильтр пользователя quer

class CustomerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Customer
        fields = ['user', 'first_name', 'last_name']

    def get_fields(self):
        fields = super().get_fields()
        current_user = self.context['request'].user
        fields['user'] = serializers.PrimaryKeyRelatedField(queryset=User.objects.filter(id=current_user.id))
        return fields
0 голосов
/ 05 марта 2019

Я бы ограничил выбор в viewset.

class MyViewset(ViewSet):
    serializer_class = CustomerSerializer
    def get_queryset(self):
        return Customer.objects.filter(user=self.request.user)
...