How to delete an object using Django Rest Framework

50,832

Solution 1

You're being redundant. The HTTP method is already DELETE, so there's no /events/delete in the url. Try this:

curl -X DELETE "http://127.0.0.1:8000/events/1/"

By default, DRF's router creates detailed urls at /event/<pk> and you GET, PUT, POST and DELETE them to retrieve, update, create and delete respectively.

Solution 2

As mentioned by Kevin Stone, the pattern you're using isn't advisable, but if you want to use it, you'll need to fix the typo in your urls for the events/delete/ mapping.

 # delete event
 url(r'^delete$/(?P<pk>\d+)',
     views.EventDetail.as_view(), name='delete_event'),

should be:

 # delete event
 url(r'^delete/(?P<pk>\d+)',
     views.EventDetail.as_view(), name='delete_event'),
Share:
50,832
user3282276
Author by

user3282276

Updated on July 09, 2022

Comments

  • user3282276
    user3282276 almost 2 years

    I am trying to write an RESTful API for my event planning app using Django Rest Framework but I am having some trouble when using views that do not expect the GET HTTP method. I have read through the tutorial on the DRF site. From what I understand after reading through the tutorial and the class based view documentation on the Django site is that if there is a class based view like this (taken from the DRF tutorial)

    class SnippetDetail(APIView):
        """
        Retrieve, update or delete a snippet instance.
        """
        def get_object(self, pk):
            try:
                return Snippet.objects.get(pk=pk)
            except Snippet.DoesNotExist:
                raise Http404
    
        def get(self, request, pk, format=None):
            snippet = self.get_object(pk)
            serializer = SnippetSerializer(snippet)
            return Response(serializer.data)
    
        def put(self, request, pk, format=None):
            snippet = self.get_object(pk)
            serializer = SnippetSerializer(snippet, data=request.DATA)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
        def delete(self, request, pk, format=None):
            snippet = self.get_object(pk)
            snippet.delete()
            return Response(status=status.HTTP_204_NO_CONTENT) 
    

    The different methods in the view correspond to the different HTTP Request methods. So if I have www.foo.com/bar it would do two different things based on what request method is sent to that address. So that means that I wouldn't have to specify anything else because the function that is executed is determined based on the method the URL is sent with. Is this correct?

    I have this view which I tried to model after the example on the DRF site

    class EventDetail(APIView):
    
        """
        Retrieve, update or delete a event instance.
        """
    
        def get_object(self, pk):
            try:
                return Event.objects.get(pk=pk)
            except Event.DoesNotExist:
                raise Http404
    
        def get(self, request, pk, format=None):
            event = self.get_object(pk)
            serializer = EventSerializer(event)
            return Response(serializer.data)
    
        def post(self, request, format=None):
            serializer = EventSerializer(data=request.DATA)
            if serializer.is_valid():
                serializer.save()
                return Response(serializer.data, status=status.HTTP_201_CREATED)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
        # def put(self, request, pk, format=None):
        #     event = self.get_object(pk)
        #     serializer = EventSerializer(event, data=request.DATA)
        #     if serializer.is_valid():
        #         serializer.save()
        #         return Response(serializer.data)
        #     return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
        def delete(self, request, pk, format=None):
            event = self.get_object(pk)
            event.delete()
            return Response(status=status.HTTP_204_NO_CONTENT
    

    which maps to these URLs

    urlpatterns = patterns('',
    
                           # Get event
                           url(r'^(?P<pk>\d+)/$', views.EventDetail.as_view(),
                               name='create_events'),
                           # list all events
                           url(r'^list/$', views.EventList.as_view(),
                               name='list_events'),
                           # url(r'^update$/(?P<pk>\d+)', #update event),
                           url(r'^create/$', views.EventDetail.as_view(),
                               name='create_events'),
                           # delete event
                           url(r'^delete$/(?P<pk>\d+)',
                               views.EventDetail.as_view(), name='delete_event'),
    
                           )
    

    which I am trying to test using CURL with this command (like suggested here DELETE using CURL with encoded URL)

    curl -X DELETE "http://127.0.0.1:8000/events/delete/1"
    

    This will seem to do what it should:

    [18/Oct/2014 22:41:27] "DELETE /events/delete/1 HTTP/1.1" 404 2707
    

    But the actual record is not deleted from my database

    Is there something here that I am forgetting to do to get these to get this to work properly?