what's different about list_route and detail_route in django-rest-framework?

后端 未结 3 1530
旧时难觅i
旧时难觅i 2021-02-20 18:06

like title,
what\'s different about list_route and detail_route in django-rest-framework?
if I want to get 1 in url xxx/book

相关标签:
3条回答
  • 2021-02-20 18:29

    detail_route, is for an instance. What I mean, method generated with detail route, will be appended after an instance method, i.e. a retrieve. {prefix}/{lookup}/

    Check : django drf router doc

    If your model is books and 1 is the id:

    class ParkingViewSet(viewsets.ModelViewSet):
    serializer_class = BookSerializer
    
    def retrieve(self, request, pk=None):
        # Here pk will be 1.
        queryset = Book.objects.get(pk=pk)         
        serializer = BookSerializer(queryset)                         
        return Response({'msg':"",'data':serializer.data, 'status':'OK'})
    

    If xxx is your instance, you should user url_path variable to change default url. Something like this:

    @detail_route(methods=['get'], url_path='(books/?P<num>\d+)')
    

    Then in the method, you will have num as a parmeter

    urls.py, will be generated with default router:

    from django.conf.urls import url, include                                        
    from recharge_card import views                                                  
    from rest_framework.routers import DefaultRouter                                 
    
    # Create a router and register our viewsets with it.                             
    router = DefaultRouter()                                                         
    router.register(r'xxx', views.XxxViewSet, base_name="xxx")  
    
    urlpatterns = [  
        url(r'^api/', include(router.urls)),                                         
    ]                                                                                
    
    0 讨论(0)
  • 2021-02-20 18:37

    **Read this and definitely you will get the difference and how to use it **

    If we have a ad hoc method (for e.g. current method which is in the same viewset that we have used for different methods, basically ad-hoc means 'this'), we can use custom route for this method, we can define our own url above the method inside the @list_route and @detail_route decorator

    The difference between the @list_route and @detail_route is the @detail_route decorator contains pk in its URL pattern and is intended for methods which require a single instance. The @list_route decorator is intended for methods which operate on a list of objects (list of records)

    Get reference through enter link description here

    For example

    **It will hit to the same url at the url.py but for @list_raoute we have append /reset-user-password/ which we have mention on @list_route to the url when we call it.(e.g 
    
    /// In url.py**
    
    router = routers.DefaultRouter()
    
    router.register(r'register', api_views.UserProfileViewSet,  base_name="userprofileviewset")
    urlpatterns = [
        url(r'^api/v1/', include(router.urls)),
    ]
    

    **////// In API call or in url call

    for create user**
    http://127.0.0.1:8000/api/v1/register/
    

    ### forget password

    http://127.0.0.1:8000/api/v1/resister/reset-user-password/
    
    )
    
    class UserProfileViewSet(viewsets.ViewSet):
        """
        IT's use to create new user(auth user). accepted method is post. 
        end point /register
        """
        permission_classes = (AllowAny,)
        serializer_class = UserProfileSerializer
    
    """
    It gives the list of all users
    """
    def list(self, request):
        queryset = UserProfile.objects.all()
        serializer = self.serializer_class(queryset, many=True)
        return Response(serializer.data)
    
    """
    It creates new user
    """
    def create(self, request):
        serializer = self.serializer_class(data=request.data)
        # check email address is exists or not.
        user_type = request.data['user_type']
        user_token = register_by_social(request.data['email'], request.data['username'], user_type)
        
        if not user_token or user_token == True:
            if not User.objects.filter(Q(email=request.data['email']) 
                | Q(username=request.data['username'])).exists():
    
                if serializer.is_valid():
                    userprofile = serializer.save()
    
                    return Response({
                        'status': status.HTTP_201_CREATED,
                        'message': 'Successfully signup new user.',
                        'token': userprofile.user.auth_token.key })
    
                return Response({
                    'status': status.HTTP_400_BAD_REQUEST,
                    'message': 'Please provided required fields.',
                    'error' : serializer.errors })
    
            return Response({
                'status': status.HTTP_409_CONFLICT,
                'message': 'Email address or username is already exists.'})
    
        return Response({
            'status': status.HTTP_200_OK,
            'message': 'Social user is already registered.',
            'token': user_token })
    
    
    @list_route(permission_classes=[IsAuthenticated], authentication_classes = (BasicAuthentication, TokenAuthentication), 
            methods=['post'], url_path='reset-user-password')
    def reset_user_password(self, request, pk=None):
        """
        It resets the user password
        """
        reset_password_serializer = UserResetPasswordSerializer(request.user, data=request.data)
        
        if reset_password_serializer.is_valid():
    
            if not request.user.check_password(request.data.get('password')):
                return Response({
                    'status': status.HTTP_400_BAD_REQUEST,
                    'message': 'Password id wrong, please enter correct password',
                    })
    
            request.user.set_password(request.data.get('new_password'))
            request.user.save()
            return Response({
                    'status': status.HTTP_201_CREATED,
                    'message': 'Password updated successfully',
                    })
    
    
    class PlayListViewSet(viewsets.ViewSet):
        permission_classes = (IsAuthenticated,)
        serializer_class = PlayListSerializer
        serializer_add_playlist_class = LikeContentSerializer
    
        @detail_route(methods=['post'], url_path='add-content-to-playlist')
        def add_playlist(self, request, pk=None):
         
            serializer = self.serializer_add_playlist_class(data=request.data)
            playlist = PlayList.objects.filter(id=pk)
            if serializer.is_valid():
                content_type = request.data['content_type']
    
                if content_type =="audio":  
                    content = Song.objects.filter(id=request.data['content'])
                    playlist[0].songs.add(content[0])
                    playlist[0].save()
                    
                 
                if content_type =="video":
                    content = Video.objects.filter(id=request.data['content'])
                    playlist[0].videos.add(content[0])
                    playlist[0].save()
                
                if content_type =="youtube":
                    content = YouTubeVideo.objects.filter(id=request.data['content'])
                    playlist[0].youtbue_videos.add(content[0])
                    playlist[0].save()
    
                return Response({
                    'status': status.HTTP_201_CREATED,
                    'message': 'Successfully playlist updated'})
    
            return Response({
                'status': status.HTTP_400_BAD_REQUEST,
                'message': 'Data is not valid, try again',
                'error' : serializer.errors })
    
    0 讨论(0)
  • 2021-02-20 18:42

    @list_route and @detail_route are extra actions that we can add to a ViewSet. Both provide a custom routing facility in view set. Any methods on the ViewSet decorated with @detail_route or @list_route will also be routed. list_route will give all the related records, whereas detail_route will provide only a particular record. For example, given a method like this on the UserViewSet class:

    class UserViewSet(ModelViewSet):
        ...
    
        @detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
        def set_password(self, request, pk=None):
    

    The following URL pattern would additionally be generated:

    URL pattern: ^users/{pk}/set_password/$ Name: 'user-set-password'
    

    For more information on routers you can visit the official Django Rest Rramewrok documentation on routers.

    If you want get xxx/books/1/ then your url.py and views.py should look like this.

    urls.py:

    url(r'^xxx/books/(?P<id>[0-9]+)$', views.myview)
    

    views.py:

    @csrf_exempt
    def myview(request , id):
    
    0 讨论(0)
提交回复
热议问题