在我的代码中,我有一个用户的视图集。 我想要的是只允许ReadOnlyModelViewSet做的Read操作( / users / 42 和 / users / )。
此外,我想要一个 / users / register 网址,我可以发布以注册新用户。
class UserViewSet(viewsets.ReadOnlyModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
@list_route(methods=['post'])
def register(request):
serializer = UserSerializer(data=request.DATA)
if serializer.is_valid():
user = User.objects.create_user(
username = serializer.init_data['username'],
password = serializer.init_data['password'],
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
几个问题:
这是正确的做法吗?
如果我将方法放在 list_route 或 detail_route 装饰器中,是否有特定的签名?因为在detail_route示例中,它始终与方法的签名相同: method_name (self,request,pk = None):
谢谢!
答案 0 :(得分:13)
您的代码几乎是正确的,您只是在注册方法上错过了正确的签名:
def register(self, request):
根据the documentation,这是正确的签名。另外the tests表示无法为路由传递其他参数,并且pk将始终为@detail_route
传递,因此您必须拥有:
@detail_route
def register(self, request, pk=None):
详细路线和
@list_route
def register(self, request):
列表路线。
但我建议你利用内置的ViewSetMixins as ModelViewSet does internally:
from rest_framework import exceptions, mixins
class UserViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
def create(self, request):
serializer = UserSerializer(data=request.DATA)
if serializer.is_valid():
user = User.objects.create_user(
username = serializer.init_data['username'],
password = serializer.init_data['password'],
)
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
对于一般用户注册,您还可以查看我正在为我的项目工作的django-registration-restframework。
我个人在项目中依赖ModelViewSet,并确保只有经过适当授权的用户才能执行某些操作。为此,您可以使用模型范围permissions或与django guardian对象特定权限相结合。
特别是使用REST API,您最终会发现您希望某些用户仅对某些对象执行操作,而无需对每个请求进行微观管理。对象级权限在这里非常有用。
答案 1 :(得分:2)
detail_route和detail_list将在DRF 3.0上弃用,请改用@action:
from rest_framework.decorators import action
@action(methods=['POST'], detail=True)
def sale(self):
...
使用detail = True表示此方法将说明该终结点表示的Model的单个实例,而当需要表示该模型的Queryset时表示False