0

Привет Я следую this Пример использования DjangoObjectPermissionsFilter.Как настроить DjangoObjectPermissions?

Я хочу создать class SampleModelPermissions(permissions.DjangoObjectPermissions) так, чтобы он удовлетворял следующее описание в моем «самодокументированного» ФПИ API:

enter image description here

Это мой код:

в 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 

в permisions.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 

Но я получаю следующее POSTMAN:

enter image description here

enter image description here

Любые советы о том, что я должен делать, чтобы получить свой API разрешений на работу, поскольку я описываю их в самодокументации?

ответ

0

Решение было признать, что has_permission охватывает GET список и POST и has_object_permissions охватывает GET деталь, PATCH и DELETE. Мне пришлось разделить мой код на эти 2 функции соответственно (помните о том, что все еще разрабатываются другие проблемы с кодом, но рассмотрена конкретная проблема, затронутая в этом вопросе):

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 
0

Есть ли другой способ управления разрешением и достижения результатов, как вы описали в документации.

В основном вы должны назначать разрешения после создания объекта. Например, вы можете использовать сигналы для назначений.

Пример DjangoObjectPermission:

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'], 
    } 

Пример сигналов:

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) 
Смежные вопросы