【问题标题】:set custom permission to model in Django设置自定义权限以在 Django 中建模
【发布时间】:2022-01-16 10:33:15
【问题描述】:

我必须在 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)

我需要对设备模型的特定权限访问取决于 用户 UserMeta 模型中的模型。 在 UserMeta 中,我有一些选择权限,例如:owner,admin,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 逻辑更新代码吗
  • 嗨,我添加了我的 drf 代码
  • 你想要对只有类型所有者的用户进行所有的 crud 操作吗?

标签: python django django-models django-rest-framework django-authentication


【解决方案1】:

您可以像这样在 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)

【讨论】:

  • 嗨,谢谢,我需要使用其令牌指定设备,例如 UsersMeta.objects.get(user=request.user,token=TOKEN)。有可能吗?
  • 我的回答解决了你原来的问题吗?
  • 不,它只是解决了我的问题的一部分,我需要知道用户对它可以通过令牌指定的特定设备具有权限,我不知道如何将令牌传递给权限类
  • 如果request.GET 的打印值无效,请尝试UsersMeta.objects.get(user=request.user,token=request.GET.get('pk') 并查看pk 是否存在。
猜你喜欢
  • 2011-04-02
  • 2017-05-27
  • 2013-09-09
  • 2021-06-24
  • 2013-09-28
  • 2018-09-10
  • 1970-01-01
  • 2013-11-20
  • 1970-01-01
相关资源
最近更新 更多