2016-07-28 4 views
3

엔드 포인트에 가입하세요 추가 :장고 나머지 프레임 워크 내가 다음과 같은 엔드 포인트를 가지고 장고 나머지 프레임 워크 (DRF)와 REST API를 만들고있어

/users/ 
/users/<pk>/ 
/items/ 
/items/<pk>/ 

하지만 엔드 포인트 추가 할 :

/users/<pk>/items/ 

물론이 항목은 외래 키가있는 항목을 해당 사용자에게 반환합니다.

현재 내 코드입니다 : 내가 DRF를 사용하고 어떻게

######################### 
##### myapp/urls.py ##### 
######################### 

from django.conf.urls import url, include 
from rest_framework.routers import DefaultRouter 
from rest_framework.decorators import api_view, renderer_classes 
from rest_framework import response, schemas 
from rest_framework_swagger.renderers import OpenAPIRenderer, SwaggerUIRenderer 

from myapp.views import ItemViewSet, UserViewSet 

# Create a router and register our viewsets with it. 
router = DefaultRouter() 
router.register(r'users', UserViewSet) 
router.register(r'items', ItemViewSet) 

@api_view() 
@renderer_classes([OpenAPIRenderer, SwaggerUIRenderer]) 
def schema_view(request): 
    generator = schemas.SchemaGenerator(title='My API') 
    return response.Response(generator.get_schema(request=request)) 

urlpatterns = [ 
    url(r'^', include(router.urls)), 
    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')), 
] 

########################## 
##### myapp/views.py ##### 
########################## 

from django.contrib.auth import get_user_model 
from rest_framework import viewsets, permissions 

from myapp.serializers import MyUserSerializer, ItemSerializer 
from myapp.models import Item 


class UserViewSet(viewsets.ReadOnlyModelViewSet): 
    queryset = get_user_model().objects.all() 
    serializer_class = MyUserSerializer 
    permission_classes = (permissions.IsAuthenticated,) 

class ItemViewSet(viewsets.ReadOnlyModelViewSet): 
    queryset = Item.objects.all() 
    serializer_class = ItemSerializer 
    permission_classes = (permissions.IsAuthenticated,) 

################################ 
##### myapp/serializers.py ##### 
################################ 

from rest_framework import serializers 
from django.contrib.auth import get_user_model 

from myapp.models import Item 

class MyUserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = get_user_model() 
     fields = ('pk', 'email',) 

class ItemSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = Item 
     fields = ('pk', 'name',) 

DRF에서이 엔드 포인트를 추가 할 수있는 좋은 방법이 주어진 있습니까?

from myapp.views import items_for_user 

urlpatterns = [ 
    url(r'^', include(router.urls)), 
    url(r'^users/(?P<pk>[0-9]+)/items/$', items_for_user), 
] 

하지만, DRF를 활용 탐색 가능한 API를 얻고, 같은 일회성 기능 뷰 코딩의 ViewSet의 사용을 대신 만들고 싶어 :

난 그냥과 같이 urls.py의 기능보기를 추가 할 수 있습니다 이.

아이디어가 있으십니까?

답변

1

알아 내려면 잠시만 기다려주세요. 뷰 집합을 사용하고 있으므로이 설정 내에서이 대답을 제공 할 것입니다.

첫째, URLConf 등록 노선들은 예를 들어, 사용자 지정 권한을 생성하여, 그것들을 요청하는 사람에 따라 그 각각 제작 된 권한으로,

router = DefaultRouter() 
router.register(r'users', UserViewSet) 
router.register(r'items', ItemViewSet) 

urlpatterns = [ 
    url(r'^', include(router.urls)), 
    url(r'^api-auth/', 
     include('rest_framework.urls', namespace='rest_framework') 
    ), 
] 

항목

여전히 /items/<pk>/에있을 것입니다, 즉, 변경되지 않은 상태로 유지 :

class IsItemOwnerPermissions(permissions.DjangoObjectPermissions): 
    """ 
    The current user is the owner of the item. 
    """ 
    def has_object_permission(self, request, view, obj): 
     # A superuser? 
     if request.user.is_superuser: 
      return True 
     # Owner 
     if obj.owner.pk == request.user.pk: 
      return True 
     return False 

다음, /user/<pk>/items/에 대한이 같은 @detail_route을 정의해야

class UserViewSet(viewsets.ReadOnlyModelViewSet): 
    # Your view set properties and methods 
    @detail_route(
     methods=['GET', 'POST'], 
     permission_classes=[IsItemOwnerPermissions], 
    ) 
    def items(self, request, pk=None): 
     """ 
     Returns a list of all the items belonging to `/user/<pk>`. 
     """ 
     user = get_user_model().objects.get(pk=pk) 
     items = user.items.all() 
     page = self.paginate_queryset(items) 
     if page is None: 
      serializer = ItemSerializer(
       objs, context={'request': request}, many=True 
      ) 
      return Response(serializer.data) 
     else: 
      serializer = ItemSerializer(
       page, context={'request': request}, many=True 
      ) 
      return self.get_paginated_response(serializer.data) 

xyz이라는 자세한 경로는 user/<pk>/xyz 경로에 해당합니다. 목록 경로 (@list_route)도 있습니다. xyzuser/xyz (예 : user/add_item)에 해당합니다. (I 잘못 달성하기 위해 시도로) /user, /user/<pk>, user/<pk>/items, /items/items/<pk> 있지만user/<user_pk>/items/<items_pk> :

위의 구조는 당신에게 제공 할 것입니다. 대신 user/<pk>/items은 사용자의 항목 목록을 제공하지만 개별 속성은 여전히 ​​/items/<pk>을 통해서만 액세스 할 수 있습니다.

난 그냥 내 프로젝트에서 작동하도록했고, 위의 코드는 귀하의 경우에 신속하게 적용됩니다. 도움이 되었기를 바랍니다.하지만 여전히 문제가있을 수 있습니다.

업데이트 :custom hyperlinked fields을 사용하여 원하는 것을 수행 할 수 있습니다. 나는 (아직) 시도하지 않았으므로 이것을 사용하는 방법을 말할 수는 없지만, 그 링크에는 좋은 예가있다.

관련 문제