Cá nhân tôi ghét loại quyền frankenmonster tùy chỉnh, theo ý kiến của tôi, nó không phải là rất thành ngữ khi nói đến khuôn khổ Django; Vì vậy, tôi đã đưa ra giải pháp sau đây - nó rất giống với cách trang trí @list_route và @detail_route hoạt động. Chúng tôi đang dựa trên thực tế là các phương pháp/chức năng là đối tượng hạng nhất
Trước hết tôi là tạo ra dectorator ví dụ:
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
Như bạn có thể nhìn thấy nó thêm một từ điển vào hàm mà nó trang trí với các tham số được truyền dưới dạng danh sách arg
Bây giờ tôi đã tạo hỗn hợp như vậy: mixin. 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 thực hiện hai việc; khi get_permissions được gọi, nó sẽ kiểm tra mà 'hành động' được thực thi, và looksup bộ sưu tập permission_classes từ 'route_action_kwargs' liên quan đến việc viewset.action_method.route_action_kwargs
khi get_serializer_class được gọi, nó cũng làm như vậy và chọn các ' serializer' từ '
Bây giờ cách route_action_kwargs' chúng ta có thể sử dụng nó:
@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)
Đối với tùy chỉnh routse chúng ta định nghĩa một cách rõ ràng, chúng tôi chỉ có thể đặt @route_action_arguments một cách rõ ràng về phương pháp này.
Về viewsets và phương pháp chung chung, chúng tôi vẫn có thể thêm chúng bằng cách sử dụng @method_decorator
@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
trang trí django.contrib.auth của không phải lúc nào những gì hữu ích khi sử dụng quan điểm chung DRF của. Khá thường xuyên bạn không thực hiện các phương thức HTTP - vì vậy không có gì để trang trí. (Và thực hiện chúng, hoặc công văn, chỉ để trang trí chúng là không có niềm vui.) Tốt hơn để sử dụng hệ thống quyền riêng của DRF trong trường hợp này. http://django-rest-framework.org/api-guide/permissions.html –