Я лично ненавижу этот вид frankenmonster пользовательских разрешений, на мой взгляд, это не очень идиоматических, когда речь идет о рамках Джанго; Итак, я придумал следующее решение - он очень похож на то, как работают декораторы @list_route и @detail_route. Мы рассчитываем на то, что методы/функции первого класса объектов
Прежде всего я создаю такую dectorator:
decorators.py
def route_action_arguments(**kwargs):
"""
Add arguments to the action method
"""
def decorator(func):
func.route_action_kwargs = kwargs
return func
return decorator
Как вы можете видеть он добавляет словарь к функции, которую он украшает параметрами, переданными как список аргументов
Теперь я создал такой mixin: mixins. py
class RouteActionArgumentsMixin (object):
"""
Use action specific parameters to
provide:
- serializer
- permissions
"""
def _get_kwargs(self):
action = getattr(self, 'action')
if not action:
raise AttributeError
print('getting route kwargs for action:' + action)
action_method = getattr(self, action)
kwargs = getattr(action_method, 'route_action_kwargs')
print(dir(kwargs))
return kwargs
def get_serializer_class(self):
try:
kwargs = self._get_kwargs()
return kwargs['serializer']
except (KeyError, AttributeError):
return super(RouteActionArgumentsMixin, self).get_serializer_class()
def get_permissions(self):
try:
kwargs = self._get_kwargs()
return kwargs['permission_classes']
except (KeyError, AttributeError):
return super(RouteActionArgumentsMixin, self).get_permissions()
Mixin делает две вещи; когда get_permissions называется, он проверяет, который «действие» выполняется, и looksup коллекции permission_classes от «route_action_kwargs», связанный с viewset.action_method.route_action_kwargs
когда get_serializer_class называется, он делает то же самое, и выбирает " сериализатору»от„
теперь путь route_action_kwargs“мы можем использовать его:
@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
"""
User and profile managment viewset
"""
queryset = User.objects.all()
serializer_class = UserSerializer
@list_route(methods=['post'])
@route_action_arguments(permission_classes=(AllowAny,), serializer=LoginSerializer)
def login(self, request):
serializer = self.get_serializer_class()(data=request.data)
Для пользовательских routse мы определяем в явном виде мы можем просто установить @route_action_arguments явно на методе.
С точкой зрения общих viewsets и методов, мы все еще можем добавить их с помощью @method_decorator
@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
декораторов django.contrib.auth является не всегда полезны при использовании общих взглядов ФПИ. Довольно часто вы вообще не реализуете методы HTTP, поэтому украшать нечего. (И реализовать их или отправить, просто чтобы украсить их, не повеселиться.) Лучше использовать в этом случае собственную систему разрешений DRF. http://django-rest-framework.org/api-guide/permissions.html –