首页 > 解决方案 > 在 drf 的一个项目中,我有端点“api/v1/invoice/#id/”,所以我想授予查看此发票的​​唯一作者的权限

问题描述

我有一个端点 /api/v1/invoice/#id/

我希望只有此发票的作者才能查看发票或工作人员应该能够查看此发票超级用户应该能够查看、更新、删除发票

我尝试在我的应用程序中创建 permissions.py 文件:

权限.py

from rest_framework.permissions import BasePermission


class AuthorGetStaffGetAdminAll(BasePermission):
    edit_methods = ("PUT", "PATCH", "DELETE")

    def has_permission(self, request, view):
        if request.user.is_authenticated:
            return True
        return False

    def has_object_permission(self, request, view, obj):
        if request.user.is_superuser:
            return True

        if obj.author == request.user and request.method not in self.edit_methods:
            return True

        if request.user.is_staff and request.method not in self.edit_methods:
            return True

        return False

序列化程序.py

class InvoiceSerializer(serializers.ModelSerializer):
    order = serializers.SlugRelatedField(slug_field='id', queryset=order.Order.objects.all())
    id = serializers.CharField(max_length=100, read_only=True)
    class Meta:
        model = invoice.Invoice
        fields = ['id', 'invoice_series', 'order', 'payment_id']

视图.py

class InvoiceDisplayView(APIView):
    permission_classes = [AuthorGetStaffGetAdminAll]

    def get(self, request, invoice_id):
        invoice = Invoice.objects.get(id__iexact=invoice_id)
        serializer = InvoiceSerializer(invoice)
        return Response(serializer.data)

网址.py

from django.urls import path
from . import views

urlpatterns = [
    path('v1/invoices/<str:invoice_id>/', views.InvoiceDisplayView.as_view(), name="invoice_view"),
]

标签: djangodjango-rest-frameworkdjango-permissions

解决方案


APIView 没有对象级权限检查。您可以使用 RetrieveUpdateDestroyAPIView 更新您的 APIView:

class InvoiceDisplayView(RetrieveUpdateDestroyAPIView):
    
    lookup_field = 'invoice_id'  # primary key
    permissions_classes = [IsAuthenticatedAndOwner]
    queryset = Invoice.objects.all()
    serializer_class = InvoiceSerializer

如果您的主键是 invoice_id 您可以这样做并且不需要 get 方法,仅此一项服务 put update delete 并单独获取,通常 primary_key 只是 id 或 pk ,在这种情况下 lookup_field 将是 'id' 或 'pk' 和您还需要更新您的网址:

urlpatterns = [
    path('v1/invoices/<int:id>/', views.InvoiceDisplayView.as_view(), name="invoice_view"),
]

推荐阅读