在 Django 中为模型设置自定义权限

set custom permission to model in Django

我必须对Django 中的模型设置一些权限,因为我在DRF 中有一些操作,我需要知道用户是否有权限这样做。 我的模型:

class Device(models.Model):
    type = models.ForeignKey(Type, on_delete=models.CASCADE)
    name = models.fields.CharField(max_length=36)
    ip = models.CharField(max_length=64, blank=True)
    password = models.CharField(max_length=62, blank=True)
    mac = models.CharField(max_length=17, blank=True)
    description = models.fields.TextField(max_length=600, blank=True)
    users = models.ManyToManyField(User,'users_device',through="UserMeta")
            
    status = models.BooleanField(default=False)

    def __str__(self):
        return self.name

class UsersMeta(models.Model):
    type_choices = [
        ("owner",'owner'),
        ('user','user'),
        ('admin','admin')
    ]
    user = models.ForeignKey(User,on_delete=models.DO_NOTHING,related_name='UserMeta_devices')
    device = models.ForeignKey(Device,models.CASCADE,related_name='UserMeta_device')
    type = models.CharField(max_length=8,choices=type_choices)
    
    token = models.UUIDField(default=uuid4,
                             editable=False,
                             unique=True)
    join_time = models.DateTimeField(auto_now_add=True)
    last_activate = models.DateTimeField(null=True,blank=True)

我需要对 设备 型号 depending 的特定权限访问 User模型在UserMeta模型中。 在 UserMeta 中,我有一些选择权限,例如:owner,admin,user,所以我要说这个User是否有权限OWNER,或者别的什么都行不行。

我不知道对不对,如果你知道请告诉我

更新:

class Device(ViewSet):
    permission_classes = [permissions.IsAuthenticated]

    ########################################################
    #                       Device                         #
    ########################################################

    @extend_schema(
        summary="Get All Devices of User",
        request={
            200: Serializer_Device,
        },
        responses={
            200: Serializer_Device(many=True),
            400: None,
        },
    )
    def list(self, request) -> Response:
        device = get_list_or_404(Device_Model, user=request.user)
        serializer = Serializer_Device(device, many=True)
        return Response(serializer.data, status=Status.HTTP_200_OK)

    @extend_schema(
        summary="Retrive a special device with the UUID token",
        responses={
            200: Serializer_Device,
            404: None,
        },
        parameters=[
            OpenApiParameter(
                name="id",
                description="Token of Device",
                allow_blank=False,
                type=OpenApiTypes.UUID,
                location=OpenApiParameter.PATH,
            )
        ],
    )
    def retrieve(self, request, pk) -> Union[Response, Http404]:
        user = request.user
        device = get_object_or_404(Device_Model, token=pk, user=user)
        serializer = Serializer_Device(device)
        return Response(serializer.data, status=Status.HTTP_200_OK)

    @extend_schema(
        summary="Full Update a Device",
        request=Serializer_Device,
        responses={
            200: Serializer_Device,
            404: None,
        },
        parameters=[
            OpenApiParameter(
                name="id",
                description="Token of Device",
                allow_blank=False,
                type=OpenApiTypes.UUID,
                location=OpenApiParameter.PATH,
            )
        ],
    )
    def update(self, request, pk) -> Response:
        device = get_object_or_404(Device_Model, token=pk, user=request.user)

        serializer = Serializer_Device(
            instance=device, data=request.data, context={"request": request}
        )

        if serializer.is_valid(raise_exception_validitor):
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(status=status.HTTP_400_BAD_REQUEST)

    @extend_schema(
        summary="Create a new device",
        request=Serializer_Device,
        responses={201: Serializer_Device, 400: dict},
    )
    def create(self, request) -> Union[Response, Http404]:
        data = request.data

        serializer = Serializer_Device(data=request.data, context={"request": request})
        if serializer.is_valid(raise_exception_validitor):
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(status=status.HTTP_400_BAD_REQUEST)

    @extend_schema(
        summary="Delete Device with Token",
        responses={
            200: Serializer_Device,
            204: None,
        },
        parameters=[
            OpenApiParameter(
                name="id",
                description="Token of Device",
                type=OpenApiTypes.UUID,
                location=OpenApiParameter.PATH,
            )
        ],
    )
    def destroy(self, request, pk) -> Union[Response, None]:

        device = get_object_or_404(Device_Model, token=pk, user=request.user)
        device.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

    @extend_schema(
        summary="Filter Device With Tyep  ",
        responses={
            200: Serializer_Device,
            404: None,
        },
        parameters=[
            OpenApiParameter(
                name="type",
                description="type of Device",
                type=OpenApiTypes.STR,
                location=OpenApiParameter.PATH,
            )
        ],
    )
    @action(
        detail=False,
        methods=["GET"],
        url_path=r"filter/(?P<type>\w+)",
        url_name="filter_type",
    )
    def filter(self, request, type) -> Union[Response, Http404]:
        user = request.user
        device = get_list_or_404(Device_Model, type=type, user=user)
        serializer = Serializer_Device(device, many=True)
        return Response(serializer.data, status=Status.HTTP_200_OK)

    ########################################################
    #                         Data                         #
    ########################################################

    @extend_schema(
        summary="get logs of the device",
        responses={
            200: Serializer_Device_Data,
            404: None,
        },
        parameters=[
            OpenApiParameter(
                name="id",
                description="Token of Device",
                type=OpenApiTypes.UUID,
                location=OpenApiParameter.PATH,
            )
        ],
    )
    @action(detail=True, methods=["GET"], url_name="data")
    def data(self, request, pk) -> Union[Response, Http404]:
        user = request.user
        token = pk
        device = get_object_or_404(Device_Model, user=user, token=token)
        data_instance = get_list_or_404(Data_Model, device=device)
        serializer = Serializer_Device_Data(data_instance, many=True)

        return Response(serializer.data, status=Status.HTTP_200_OK)

    ########################################################
    #                       Command                        #
    ########################################################

    @extend_schema(
        summary="Get the last command",
        responses={
            200: Serializer_Command,
            404: OpenApiTypes.OBJECT,
        },
        parameters=[
            OpenApiParameter(
                "id",
                OpenApiTypes.UUID,
                location=OpenApiParameter.PATH,
                description="Toekn Device",
            )
        ],
    )
    @action(detail=True, methods=["GET"], url_name="command")
    def command(self, request, pk) -> Union[Response, Http404]:  # Retrieve Command

        data = request.data
        status = get_object_or_404(Command_Model, device=pk)
        serializer = Serializer_Command(status)
        return Response(serializer.data, status=Status.HTTP_200_OK)

您可以像这样在 DRF 中定义您的自定义权限:

permissions.py:

from rest_framework.permissions import BasePermission

class IsOwner(BasePermission):
    """
       Allows access only to owners
    """

    def has_permission(self, request, view):
       pk = request.GET.get('pk')
       user_meta = UsersMeta.objects.filter(user=request.user, token=pk).first()
       return True if user_meta and user_meta.type == "owner" else False

用法:

from rest_framework.views import APIView
from rest_framework.response import Response

from .permissions import  IsOwner 

class YourView(APIView):
    permission_classes = (IsOwner,)

    def get(self, request, format=None):
        content = {
             'status': 'owner users'
        }
        return Response(content)