私はこの質問に類似するいくつかの記事を見ましたが、私の問題を解決するものはありません。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'),
]
ありがとうございました! get_objectをオーバーライドしないで、私がスーパーユーザーである場合、get_objectによって呼び出されるquerysetは、プライマリキーに一致するユーザーではなくすべてのユーザーを返します(オーバーライドget_querysetはすべて4を返します)。私は詳細ビューとリストビュー(またはpkがリストされているかどうかに関係なく)であれば、get_querysetの動作を違うようにする方法がわかりません。したがって、detail_viewは4つの応答を取得し、エラーが発生します。 – Diesel