2013-09-05 7 views
21

मैं संसाधन 'उपयोगकर्ता' तक पहुंचने के लिए Django REST Framework का उपयोग कर रहा हूं।Django REST ढांचे ऑब्जेक्ट स्तर अनुमतियाँ

उपयोगकर्ता की जानकारी व्यक्तिगत है, इसलिए मैं सिस्टम पर हर उपयोगकर्ता को सूचीबद्ध करने का अनुरोध नहीं करना चाहता, UNLESS वे एक व्यवस्थापक हैं।

यदि उपयोगकर्ता अपनी आईडी निर्दिष्ट करता है, और वे लॉग इन हैं, तो मैं चाहता हूं कि वे उनके विवरण देख सकें और उन्हें संशोधित कर सकें (यदि संभव हो तो पोस्ट हटाएं)।

तो संक्षेप में, किसी भी व्यक्ति के लिए जीईटी विधि को अनुमति न दें जो व्यवस्थापक नहीं है और उपयोगकर्ताओं को उनकी जानकारी देखने पर लॉग इन पर हटा दें।

class UserPermissions(permissions.BasePermission): 
    """ 
    Owners of the object or admins can do anything. 
    Everyone else can do nothing. 
""" 

    def has_permission(self, request, view): 
     # if admin: True otherwise False 
    def has_object_permission(self, request, view, obj): 
     # if request.user is the same user that is contained within the obj then allow 

यह काम नहीं किया:

तो मैं कस्टम अनुमति वर्ग बनाया। कुछ डीबगिंग के बाद मुझे पता चला कि यह पहले_प्रमिशन की जांच करता है, फिर जांच करता है has_object_permission। तो अगर हम पहले नहीं पाते हैं कि पहली बार GET/उपयोगकर्ता/बाधा है, तो यह अगले जीईटी/उपयोगकर्ता/आईडी पर भी विचार नहीं करेगा।

तो संक्षेप में, क्या किसी को पता है कि मैं इसे काम करने के बारे में कैसे जाना चाहूंगा?

धन्यवाद :)

संपादित करें:

मैं उपयोग कर रहा था ModelViewSets है, जो के रूप में मैं वर्णित इस समस्या है।

लेकिन अगर आप विस्तार से साथ सूची कार्यक्षमता विभाजित तो आप उन्हें दे सकते हैं अलग अनुमति कक्षाएं:

class UserList(generics.ListCreateAPIView): 
    queryset = User.objects.all() 
    serializer_class = UserSerializer 
    permission_classes=(UserPermissionsAll,) 

class UserDetail(generics.RetrieveUpdateDestroyAPIView): 
    queryset = User.objects.all() 
    serializer_class = UserSerializer 
    permission_classes=(UserPermissionsObj,) 

class UserPermissionsAll(permissions.BasePermission): 
""" 
Owners of the object or admins can do anything. 
Everyone else can do nothing. 
""" 

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

class UserPermissionsObj(permissions.BasePermission): 
""" 
Owners of the object or admins can do anything. 
Everyone else can do nothing. 
""" 

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

     return obj == request.user 
+0

रासायनिक प्रोग्रामर से नीचे का समाधान 'विचारों 'के साथ काम करेगा। – jfunk

उत्तर

18

मैं पिछले एक कस्टम अनुमति का उपयोग करने में यह किया है और अधिरोहित has_object_permission निम्नलिखित की तरह:

from rest_framework import permissions 


class MyUserPermissions(permissions.BasePermission): 
    """ 
    Handles permissions for users. The basic rules are 

    - owner may GET, PUT, POST, DELETE 
    - nobody else can access 
    """ 

    def has_object_permission(self, request, view, obj): 

     # check if user is owner 
     return request.user == obj 

आप इस तरह के विशेष अनुरोध प्रकार से इनकार (उदाहरण के सभी उपयोगकर्ताओं के लिए प्राप्त अनुरोधों की अनुमति देने के लिए) के रूप में कुछ और अधिक विस्तृत कर सकते हैं:

class MyUserPermissions(permissions.BasePermission): 

    def has_object_permission(self, request, view, obj): 

     # Allow get requests for all 
     if request.method == 'GET': 
      return True 
     return request.user == obj 

फिर अपने ध्यान में रखते हुए आप इसे अनुमतियाँ वर्ग का उपयोग करने के बताओ:

from my_custom_permissions import MyUserPermissions 

class UserView(generics.ListCreateAPIView): 
    ... 
    permission_classes = (MyUserPermissions,) 
    ... 
10

मैं एक ऐसी ही जरूरत है। आइए मेरे ऐप को x पर कॉल करें। यहां मैं क्या आया था।तब x/permissions.py में

# viewsets.py 
from rest_framework import mixins, viewsets 

class DetailViewSet(
    mixins.CreateModelMixin, 
    mixins.RetrieveModelMixin, 
    mixins.UpdateModelMixin, 
    mixins.DestroyModelMixin, 
    viewsets.GenericViewSet): 
    pass 

class ReadOnlyDetailViewSet(
    mixins.RetrieveModelMixin, 
    viewsets.GenericViewSet): 
    pass 

class ListViewSet(
    mixins.ListModelMixin, 
    viewsets.GenericViewSet): 
    pass 

:: फिर x/views.py में

# permissions.py 
from rest_framework import permissions 

class UserIsOwnerOrAdmin(permissions.BasePermission): 
    def has_permission(self, request, view): 
     return request.user and request.user.is_authenticated() 

    def check_object_permission(self, user, obj): 
     return (user and user.is_authenticated() and 
      (user.is_staff or obj == user)) 

    def has_object_permission(self, request, view, obj): 
     return self.check_object_permission(request.user, obj) 

:

पहले, इस x/viewsets.py में डाल

# views.py 
from x.viewsets import DetailViewSet, ListViewSet 
from rest_framework import permissions 

class UserDetailViewSet(DetailViewSet): 
    queryset = User.objects.all() 
    serializer_class = UserDetailSerializer 
    permission_classes = (UserIsOwnerOrAdmin,) 

class UserViewSet(ListViewSet): 
    queryset = User.objects.all() 
    serializer_class = UserSerializer 
    permission_classes (permissions.IsAdminUser,) 

वैसे, चलता है कि आप उपयोग कर सकते हैं differe उन दो विचारों के लिए nt serializer, जिसका अर्थ है कि आप व्यू में retrieve व्यू के मुकाबले अलग-अलग विशेषताओं को दिखा सकते हैं!

# serializers.py 
class UserSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = User 
     fields = ('username', 'url',) 

class UserDetailSerializer(serializers.HyperlinkedModelSerializer): 
    class Meta: 
     model = User 
     fields = ('url', 'username', 'groups', 'profile', 'password',) 
     write_only_fields = ('password',) 

फिर x/urls.py में: उदाहरण के लिए:

# urls.py 
from x import views 
from rest_framework import routers 

router = routers.DefaultRouter() 
router.register(r'users', views.UserViewSet) 
router.register(r'users', views.UserDetailViewSet) 

... 

मैं हल्का हैरान हूँ कि router एक ही पैटर्न दो बार स्वीकार कर लिया था, लेकिन यह काम करने के लिए प्रकट होता है।

चेतावनी पाठभेद: मैं एपीआई ब्राउज़र के माध्यम से यह सब काम करता है की पुष्टि की है, लेकिन मैं प्रयास नहीं किया है एपीआई के माध्यम से अभी तक अद्यतन करने।

6

ठोकर-upons के लिए, documentation वस्तु स्तर अनुमति की सीमाओं के तहत कहते हैं:

For performance reasons the generic views will not automatically apply object level permissions to each instance in a queryset when returning a list of objects. 

तो, विवरण देखने के कार्य करेगी, लेकिन सूची के लिए, आप वर्तमान उपयोगकर्ता के खिलाफ filter की आवश्यकता होगी।

6

@ विल-हार्ट के उत्तर के लिए बस एक और बात।

DRF3 प्रलेखन में,

नोट: उदाहरण के स्तर के has_object_permission विधि केवल, दृश्य-स्तरीय has_permission चेकों को पहले से ही

इसलिए बीत चुके हैं, तो कहा जाएगा has_permission निर्दिष्ट किया जाना चाहिए has_object_permission का उपयोग करने के लिए। जब उपयोगकर्ता की सूची प्राप्त करने की कोशिश करता है

from rest_framework import permissions 

class MyUserPermissions(permissions.BasePermission): 

    def has_permission(self, request, view): 
     return True 

    def has_object_permission(self, request, view, obj): 
     return request.user == obj 

हालांकि, कोड ऊपर किसी को भी जाने की अनुमति दे देंगे। इस मामले में, action के अनुसार अनुमति देनी होगी, HTTP method के अनुसार यह बेहतर होगा।

from rest_framework import permissions 

def has_permission(self, request, view): 
    if request.user.is_superuser: 
     return True 
    elif view.action == 'retrieve': 
     return True 
    else: 
     return False 

def has_object_permission(self, request, view, obj): 
    if request.user.is_superuser: 
     return True 
    elif view.action == 'retrieve': 
     return obj == request.user or request.user.is_staff