Как добавить ситуационное поле в сериализатор? - PullRequest
0 голосов
/ 02 апреля 2019

Я пытаюсь найти лучший способ справиться с ситуацией, когда у модели может быть конфиденциальная информация, которую я хочу, чтобы только owner мог видеть.

Например, магазин ниже:

class Store(models.Model):
    owner = models.ForeignKey(Account, on_delete=models.DO_NOTHING)
    name = models.CharField(max_length=128)
    license= models.CharField(max_length=128)
    menu = models.ManyToManyField(Product)
    address = models.ForeignKey(Address, on_delete=models.DO_NOTHING, blank=True, null=True)

class StoreSerializer(serializers.ModelSerializer):
    owner = AccountSerializer(read_only=True)
    menu = ProductSerializer(many=True, read_only=True)
    address = AddressSerializer(read_only=True)

    class Meta:
        model = Store

        fields = ('owner', 'name', 'menu', 'address', 'license')

В этом примере я хочу, чтобы все пользователи могли найти магазины, но поле license должно быть доступно только для CRUD, если пользователь является владельцем этого объекта.

Каково оптимальное решение в этом случае?Мои варианты на данный момент выглядят так:

A) Создайте отдельный сериализатор для типа владельца

B) Превратите лицензию в SerializerMethodField и предоставьте ее оттуда

Iмне интересно, что является лучшей практикой и есть ли другие, более элегантные способы сделать это.

1 Ответ

0 голосов
/ 03 апреля 2019

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

get_serializer_class (self)

Возвращает класс, который должен использоваться для сериализатора.По умолчанию возвращается атрибут serializer_class.

Может быть переопределен для обеспечения динамического поведения, такого как использование разных сериализаторов для операций чтения и записи, или , предоставляющих разные сериализаторы разным типам пользователей.

Это также позволит вам проверить условие владения Store внутри переопределенного get_serializer_class представления, наследуемого от класса GenericAPIView, и выбирать между использованием того или иного сериализатора.Пример этого:

class UserList(generics.ListCreateAPIView):

    queryset = Store.objects.all()
    permission_classes = (IsAuthenticated,)

    def get_serializer_class(self):
        # Here you will provide the implementation of the checking function
        if self.request.user.is_store_owner():
            return PrivateStoreSerializer
        return PublicStoreSerializer
...