#django #django-rest-framework
#django #django-rest-framework
Вопрос:
Я пытаюсь найти наилучший способ справиться с ситуацией, когда модель может содержать конфиденциальную информацию, которую я хочу, чтобы 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) Создайте отдельный сериализатор для типа owner
Б) Превратить license в SerializerMethodField и при необходимости предоставить его оттуда
Мне интересно, какая практика лучше и есть ли другие, более элегантные способы сделать это.
Комментарии:
1. лучшей практикой является вариант A IMO, и это то, что я видел, как делают другие. В будущем вам будет проще расширять / модифицировать код и у вас будет лучшая организация кода. Выбор того, какой сериализатор использовать, также логически принадлежит уровню представления, поскольку это определяет представление. Представления DRF изначально предусматривают такого рода переключение сериализатора.
2. У вас должен быть отдельный сериализатор, и вы должны решить, какой сериализатор использовать для просмотра. Поскольку авторизация происходит в режиме просмотра.
Ответ №1:
Лучшим способом, на мой взгляд, было бы создать два разных сериализатора, в зависимости от пользователя, который собирается выполнить запрос. Перефразировка из DRF Docs:
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
Комментарии:
1. Специфично для строки if self.request.user.is_store_owner(): как мне получить доступ к запрашиваемому объекту для сравнения с зарегистрированным пользователем?
2. @SaumilPatel На самом деле, та же самая переменная
self.request.user
здесь выдаст вам пользователя, который выполнил запрос.