Dans mon code, j'ai un ensemble de vues pour l'utilisateur. Je souhaite autoriser uniquement les opérations de lecture (/users/42 et/users/) auxquelles le ReadOnlyModelViewSet fonctionne parfaitement.
De plus, je veux avoir un/utilisateurs/registre URL que je peuxPOSTERpour enregistrer un nouvel utilisateur.
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)
Couple de questions:
Serait-ce la bonne façon de faire cela?
Existe-t-il un signature spécifique pour une méthode si je la mets dans un list_route ou le detail_route decorator? car dans les exemples detail_route sa signature est toujours la même pour la méthode: nom_méthode (self, request, pk = None):
merci!
Votre code est presque correct, il vous manque la signature correcte sur la méthode du registre:
def register(self, request):
C'est la signature correcte selon la documentation . De plus les tests suggèrent qu'il n'est pas possible de passer un paramètre supplémentaire pour le routage et que pk sera toujours passé pour un @detail_route
, de sorte que vous devriez avoir:
@detail_route
def register(self, request, pk=None):
pour les itinéraires détaillés et
@list_route
def register(self, request):
pour les itinéraires de liste.
Cependant, je vous suggèrerais de tirer parti de - ViewSetMixins intégré comme ModelViewSet le fait en interne :
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)
Pour les inscriptions des utilisateurs en général, vous pouvez également consulter Django-registration-restframework que je travaille actuellement pour mon projet.
Personnellement, je m'appuie sur ModelViewSet dans mes projets et m'assure que seuls les utilisateurs dûment autorisés peuvent effectuer certaines actions. Pour ce faire, vous pouvez utiliser le modèle permissions ou en combinaison avec Django Guardian des autorisations spécifiques à un objet.
Surtout avec une API REST, vous en arriverez finalement au point où vous voudriez que certains utilisateurs effectuent des actions uniquement sur certains objets, sans avoir à microgérer chaque demande. Les autorisations de niveau objet peuvent être très utiles ici.
detail_route et detail_list seront obsolètes sur DRF 3.0, utilisez plutôt @action:
from rest_framework.decorators import action
@action(methods=['POST'], detail=True)
def sale(self):
...
Utilisez detail = True lorsque cette méthode ne prend en compte qu'une seule instance du modèle représenté par ce noeud final et False lorsqu'il doit représenter un ensemble de requêtes de ce modèle.