Django rest framework 如何自定义DjangObjectPermissions?

Django rest framework 如何自定义DjangObjectPermissions?,django-rest-framework,django-permissions,django-guardian,Django Rest Framework,Django Permissions,Django Guardian,您好,下面是使用DjangObjectPermissionsFilter的示例 我想创建类SampleModelPermissionspermissions.djangObjectPermissions,以便它满足我自己记录的DRF API中的以下描述: 这是我的代码: 在models.py中: class Sample(models.Model): created = models.DateTimeField(default=datetime.datetime.utcnow, bla

您好,下面是使用DjangObjectPermissionsFilter的示例

我想创建类SampleModelPermissionspermissions.djangObjectPermissions,以便它满足我自己记录的DRF API中的以下描述:

这是我的代码:

在models.py中:

class Sample(models.Model):
    created = models.DateTimeField(default=datetime.datetime.utcnow, blank=True, null=True)
    last_modified = models.DateTimeField(default=datetime.datetime.utcnow, blank=True, null=True)
    owner = models.ForeignKey(User, blank=True, null=True, related_name='sample_owner')
    text = models.TextField(default='', blank=True, null=True)

    class Meta:
        permissions = (
            ('view_sample', "can view sample"),
        )

    def __unicode__(self):
        return self.text

    def __str__(self):
        return self.text
在views.py中:

class SampleViewSet(viewsets.ModelViewSet):
    '''
    * Model Description: Sample is a sample model.
    * CRUD on Sample model
    * C - CREATE - POST /sample/ - allowed as long as owner is the user creating the object 
    * R - READ - GET /sample/ (list) - user can see objects it owns
    * R - READ - GET /sample/[id]/ (detail) - user can see detail page of objects it owns
    * U - UPDATE - PATCH /sample/[id]/ - allowed for owner
    * D - DELETE - DELETE /sample/[id]/ - allowed for owner
    * Note in the case of a nested model A where a field f points to an instance of another model B, you can set f's value to an instance b of B by PATCHing or POSTing with f_id = [the id of b]. Yes, whenever f points to a foreign model, f is read only and f_id is write only.
    '''
    queryset = Sample.objects.all()
    filter_backends = (DjangoFilterBackend, SearchFilter, OrderingFilter, DjangoObjectPermissionsFilter,)  
    permission_classes = (SampleModelPermissions,)
    filter_fields = '__all__'
    serializer_class = SampleSerializer
在permissions.py中

class SampleModelPermissions(permissions.DjangoObjectPermissions):

    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
        'HEAD': ['%(app_label)s.view_%(model_name)s'],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    logger.info('in SampleModelPermissions')

    def has_object_permission(self, request, view, obj):
        logger.info('in SampleModelPermissions has_object_permission')
        print 'permissions.SAFE_METHODS: ', permissions.SAFE_METHODS
        if request.method in permissions.SAFE_METHODS:
            return request.user == obj.owner or True # need to modify so can see own stuff
        elif request.method == 'POST':
            print 'checking if user has perm to create obj'
            return True # request.user == obj.owner
        elif request.method == 'PATCH': 
            return request.user == obj.owner
        elif request.method == 'DELETE':
            return request.user == obj.owner
        return False
但我从《邮递员》中得到了以下信息:


关于如何让API权限按照我在自我文档中的描述工作的任何提示?

是否有其他方法来管理权限并实现文档中描述的结果

在大多数情况下,您必须在创建对象后分配权限。例如,您可以使用信号来分配权限

示例DjangObjectPermission:

示例信号:

from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import Sample

@receiver(post_save, sender=Sample, dispatch_uid="sample_assign_permission")
def permission_assign(sender, instance, created, **kwargs):
    if created:
        assign_perm('view_sample' self.request.user, instance)
        assign_perm('change_sample', self.request.user, instance)
        assign_perm('add_sample', self.request.user, instance)
        assign_perm('delete_sample', self.request.user, instance)

解决方案是识别具有权限的对象包括GET list和POST,以及具有权限的对象包括GET detail、PATCH和DELETE。我不得不将我的代码分为这两个函数,因此请记住,仍然要解决代码的其他问题,但本问题中涉及的具体问题如下:

class SampleModelPermissions(permissions.DjangoObjectPermissions):

    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
        'HEAD': ['%(app_label)s.view_%(model_name)s'],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    logger.info('in SampleModelPermissions')

    def has_permission(self, request, view):
        logger.info('in SampleModelPermissions has_permission')
        if request.method in permissions.SAFE_METHODS:
            logger.info('SampleModelPermissions: has_permission: listing samples for user: ' + str(request.user.id))
            return True
        elif request.method == 'POST':
            suggested_owner = None
            try:
                logger.info('SampleModelPermissions: has_permission: request dict should have a suggested owner: ' + str(dict(request.data.iterlists())))
                suggested_owner = int(dict(request.data.iterlists())['owner_id'][0])
            except:
                logger.error('SampleModelPermissions: has_permission: request made without owner_id: ' + str(dict(request.data.iterlists())))
                return False
            return request.user.id == suggested_owner

    def has_object_permission(self, request, view, obj):
        logger.info('in SampleModelPermissions has_object_permission')
        print 'permissions.SAFE_METHODS: ', permissions.SAFE_METHODS
        if request.method in permissions.SAFE_METHODS:
            return request.user == obj.owner or True # need to modify so can see own stuff
        elif request.method == 'PATCH': 
            return request.user == obj.owner
        elif request.method == 'DELETE':
            return request.user == obj.owner
        return False
class SampleModelPermissions(permissions.DjangoObjectPermissions):

    perms_map = {
        'GET': ['%(app_label)s.view_%(model_name)s'],
        'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
        'HEAD': ['%(app_label)s.view_%(model_name)s'],
        'POST': ['%(app_label)s.add_%(model_name)s'],
        'PUT': ['%(app_label)s.change_%(model_name)s'],
        'PATCH': ['%(app_label)s.change_%(model_name)s'],
        'DELETE': ['%(app_label)s.delete_%(model_name)s'],
    }

    logger.info('in SampleModelPermissions')

    def has_permission(self, request, view):
        logger.info('in SampleModelPermissions has_permission')
        if request.method in permissions.SAFE_METHODS:
            logger.info('SampleModelPermissions: has_permission: listing samples for user: ' + str(request.user.id))
            return True
        elif request.method == 'POST':
            suggested_owner = None
            try:
                logger.info('SampleModelPermissions: has_permission: request dict should have a suggested owner: ' + str(dict(request.data.iterlists())))
                suggested_owner = int(dict(request.data.iterlists())['owner_id'][0])
            except:
                logger.error('SampleModelPermissions: has_permission: request made without owner_id: ' + str(dict(request.data.iterlists())))
                return False
            return request.user.id == suggested_owner

    def has_object_permission(self, request, view, obj):
        logger.info('in SampleModelPermissions has_object_permission')
        print 'permissions.SAFE_METHODS: ', permissions.SAFE_METHODS
        if request.method in permissions.SAFE_METHODS:
            return request.user == obj.owner or True # need to modify so can see own stuff
        elif request.method == 'PATCH': 
            return request.user == obj.owner
        elif request.method == 'DELETE':
            return request.user == obj.owner
        return False