Как переопределить POST, PATCH & УДАЛИТЬ методы для нескольких ViewSets, чтобы я мог добавить обязательный параметр backend?Переопределить методы POST, PATCH & DELETE
Логика. Я создаю приложение с несколькими арендаторами, которое имеет «tenant_id» во всех соответствующих таблицах. Этот tenant_id идентифицирует арендатора, и поэтому все запросы должны включать этот родительский ключ, чтобы пользователи не видели/модифицировали контент, который не принадлежит им.
Для Get запросов, я создал пользовательский фильтр бэкенд, который позволит мне добавить обязательный объект фильтра, чтобы ограничить то, что пользователь может получить
class CustomFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see entries related to their tenant.
"""
def filter_queryset(self, request, queryset, view):
tenant_id = get_tenant_id_from_token(request)
return queryset.filter(is_deleted=False, tenant_id=tenant_id)
Я потом добавил этот фильтр ко всем классам Viewset ПОСРЕДСТВОМ filter_backends =()
опция
Вопрос в том, есть ли способ достичь того же для POST, PATCH, DELETE запросов?
Мое настоящее мышление заключается в том, что можно было бы переопределить метод model.save
для всех моделей? Но это не позаботится об HTTP-методе DELETE
.
Прозрачный tenant_id:
В моделях tenant_id, конечно, обязательно. Тем не менее, я не хочу принуждать веб-клиента/мобильного клиента всегда предоставлять tenant_id, поскольку я могу получить его из токена JWT пользователя. т. е. tenant_id должен быть прозрачным для веб-приложения.
EDIT 2
Проблема, я хочу, чтобы тихо/спокойно/за кадром добавить tenant_id
без веб/мобильное приложение быть в курсе. Значение Я не хочу, чтобы приложения, использующие API, отправляли ключ JSON tenant_id
.
образца Модель
class SampleModel(models.Model):
"""
Sample model
"""
title = models.CharField(max_length=100)
tenant = models.ForeignKey(Tenant, on_delete=models.PROTECT)
class CustomFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see entries related to their tenant.
"""
def filter_queryset(self, request, queryset, view):
tenant_id = get_tenant_id_from_token(request)
return queryset.filter(is_deleted=False, tenant_id=tenant_id)
class SampleViewSet(ListCreateRetrieveUpdateViewSet):
"""
Sample viewset
"""
serializer_class = SampleModelSerializer
permission_classes = (HasPermission)
queryset = SampleModel.objects.all()
filter_backends = (CustomFilterBackend,)
Добавляя filter_backends всем viewsets, все GET запросы теперь включают tenant_id. Так что я хочу добиться того же, что и для всех других методов HTTP, особенно POST и PATCH
От чтения кажется, что мне нужно переопределить сериализаторы? Можно ли это сделать СУХОЙ? До сих пор я не понял, как
JWT, где я получаю tenant_id имеет полезную нагрузку, глядя, как это после создания пользовательского jwt_payload_handler
:
{
"exp": 1477069682,
"is_superuser": true,
"email": "[email protected]",
"tenant_id": 1, #THE TENANT ID
"user_id": 1,
"username": "[email protected]"
}
Использует аутентификацию Django. Кроме того, 'ForeignKey' не объявляются с помощью' _id', и я исправил модель образца, которую я дал. В вашем предположении, где бы я разместил «CurrentTenantDefault»? Кроме того, идентификатор арендатора должен быть извлечен из частного раздела токена JWT. Я использую 'django-rest-framework-jwt' и при входе в систему я добавил tenant_id к токену. См. Пример, который я добавил в вопрос. – lukik
Обычно я храню его в модуле 'serializers' или когда сериализаторы разделены на несколько модулей, что-то вроде' serializers.core'. Я обновил ответ на примере «CurrentTenantDefault», используя функцию 'get_tenant_id_from_token'. –
Спасибо, сэр. Это работает так, как ожидалось, и его просто понять – lukik