2017-07-27 4 views
0

私はこの質問に類似するいくつかの記事を見ましたが、私の問題を解決するものはありません。Django Rest Framework - ユーザーのリストまたは許可に基づくModelViewSetを持つ単一のユーザー

私はDjango Rest FrameworkのModelViewSetを使用しています。詳細ビューとリストビューの2つのビューがあります。

スーパーユーザーが自分のリストビューにアクセスすると、彼はすべてのユーザーを取得します。通常のユーザーがリストビューにアクセスすると、彼は自分自身しか見ることができません。

スーパーユーザーが詳細ビューにアクセスすると、任意のユーザーを表示できます。通常のユーザーが自分以外の詳細ビューにアクセスすると、認証エラーが発生します。

私は最初にこれをアクセス許可のみで試みましたが、リストビューのすべてのクエリセットでは、has_object_permissionは実行されず、認証された非スーパーユーザーが全員を表示できるようになりました。これは、オブジェクト権限はgetコマンドでのみ実行されるためです。私はget_objectをオーバーライドしようとしましたが、get_objectはリストビューに対して呼び出されないので、違いはありませんでした。だから私はget_objectsなしでget_quertysetをオーバーライドしようとしましたが、これは私の詳細ビューを壊しました。

私が理解しているのは、詳細ビューのためにget_objectが最初に呼び出され、どちらかをオーバーライドしないとget_querysetが呼び出されるということです。しかし、私がget_querysetをオーバーライドすると、それは私の詳細ビューとget_object(それは主キーに基づいてフィルタリングしません)の通常の機能を壊します。私が見るよりも、舞台裏でもっと多くのことが起こっているはずです。これを修正するためにget_querysetを書く方法がなければなりません。これは普通のDjangoのバージョンは私がやっていないことです。

以下は私が実装したものですが、なぜ私はget_objectをオーバーライドする必要があるのか​​分かりません。 get_querysetのみをオーバーライドすると、詳細ビ​​ューが壊れて、プライマリキーに基づいてフィルタリングされた1人のユーザではなく、スーパーユーザとしてログインしたときにすべてのユーザが返されます。この動作を修正するにはget_objectを使用せずにget_querysetをオーバーライドする方法はありますか?

再生回数:

class UserViewSet(viewsets.ModelViewSet): 
    queryset = User.objects.all() 
    serializer_class = UserSerializer 
    permission_classes = (AllowPostAnyReadAuthenticatedUser,) 

    def get_queryset(self): 
     user = self.request.user 
     if user.is_superuser: 
      return User.objects.all() 
     return User.objects.filter(username=user.username) 

    def get_object(self): 
     obj = get_object_or_404(User.objects.filter(id=self.kwargs["pk"])) 
     self.check_object_permissions(self.request, obj) 
     return obj 

権限:

class AllowPostAnyReadAuthenticatedUser(permissions.BasePermission): 

    def has_permission(self, request, view): 
     # Allow anyone to register 
     if request.method == "POST": 
      return True 
     # Must be authenticated to view 
     else: 
      return request.user and is_authenticated(request.user) 

    def has_object_permission(self, request, view, obj): 
     # Any view method requires you to be the user 
     return obj.id == request.user.id or request.user.is_superuser 

シリアライザ:

class UserSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = User 
     fields = ('username', 'email', 'id', 'password') 
     read_only_fields = ('id',) 
     extra_kwargs = { 
      'password': {'write_only': True} 
     } 

のURL:

userList = views.UserViewSet.as_view({ 
    'get': 'list', 
    'post': 'create' 
}) 

userDetail = views.UserViewSet.as_view({ 
    'get': 'retrieve', 
    'put': 'update', 
    'patch': 'partial_update', 
    'delete': 'destroy' 
}) 

urlpatterns = [ 
    url(r'^$', userList, name='users'), 
    url(r'^(?P<pk>\d+)$', userDetail, name='user'), 
] 

答えて

1

これは正しく実行されています!あなたのビューでget_objectメソッドを無効にする必要はありませんが、ModelViewSet checks your permissions in get_objectです。

+0

ありがとうございました! get_objectをオーバーライドしないで、私がスーパーユーザーである場合、get_objectによって呼び出されるquerysetは、プライマリキーに一致するユーザーではなくすべてのユーザーを返します(オーバーライドget_querysetはすべて4を返します)。私は詳細ビューとリストビュー(またはpkがリストされているかどうかに関係なく)であれば、get_querysetの動作を違うようにする方法がわかりません。したがって、detail_viewは4つの応答を取得し、エラーが発生します。 – Diesel

関連する問題