2016-07-28 18 views
3

を追加:ジャンゴ休憩フレームワーク - 私は、次のエンドポイントを持っているDjangoの残りのフレームワーク(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で、このエンドポイントを追加するための良い方法が与えられ、ありますか?

私はそうのようなurls.pyに機能ビューを追加することができます。

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 sを利用したいですこの。

アイデア?

答えて

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)もあります。 xyzという名前のものはuser/xyz(たとえばuser/add_item)に対応します。 (私が間違って達成しようとしたとして)/user/user/<pk>user/<pk>/items/items、および/items/<pk>ではなくuser/<user_pk>/items/<items_pk>

上記の構造はあなたを与えるだろう。代わりにuser/<pk>/itemsはユーザーのアイテムのリストを表示しますが、個々のプロパティは引き続き/items/<pk>を介してのみアクセスできます。

これは私のプロジェクトで動作するようになったばかりで、上記のコードはあなたのケースに迅速に対応しています。それがあなたを助けてくれることを願っていますが、まだそこに問題があるかもしれません。

更新:custom hyperlinked fieldsを使用してください。私はそれを試していない(まだ)ので、私はこれらを使用する方法を言うことはできませんが、そのリンク上の良い例があります。

関連する問題