Lhou A
Lhou A

Reputation: 69

django update record in database

I tried following code to update records in table but this creates new record instead of updating. What I need is update resevedplaces in table instead of creating new record

Here is my code , thank you:

view :

class ReservationCancelView(mixins.RetrieveModelMixin,        mixins.ListModelMixin, mixins.DestroyModelMixin,               mixins.CreateModelMixin,mixins.UpdateModelMixin,                viewsets.GenericViewSet):
#Model = Reservation
serializer_class = ReservationCSerializer
permission_classes = (permissions.IsAuthenticated,)    

def get_queryset(self):
    resid = self.request.POST.get('id')  
    Res= Reservation.objects.get(id=resid)
    #Res.reservedplaces =F('reservedplaces ') - 1
    #Res.save()
    return Res

def post(self, request, token=None, format=None):
    resid = self.request.POST.get('id')  
    travel_id = self.request.POST.get('travel_id')  

    Res= Reservation.objects.get(id=resid)         
    Res.reservedplaces =F('reservedplaces ') - 1
    Res.travel_id = travel_id
    Res.save()

serializer

class ReservationCSerializer(serializers.ModelSerializer):
    user = Serializers.PrimaryKeyRelatedField(read_only=True,default=serializers.CurrentUserDefault())

  class Meta:
    model = Reservation
    fields = ('__all__')

urls.py

router.register(r'cancelreservation', ReservationCancelView,'reservationcancel')

And here is post request :

 let data = {
               'travel_id': rideID ,
               'id' : resID,
               'address' : address,
               'reservedplaces': nbplaces            
              };

   $.ajax({
        method: 'POST',
        url: '/api/cancelreservation/',
        datatype: 'json',
        headers: {
            'Authorization': 'Token ' + localStorage.token
        },
        data: data,
        success: function (response) {
        }
    })

Upvotes: 2

Views: 1599

Answers (1)

Nathan Smith
Nathan Smith

Reputation: 133

Django rest framework doesn't use post() like your used too.

From the documentation:

A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as .get() or .post(), and instead provides actions such as .list() and .create().

The GenericViewSet that you are extending from is going to route POST requests to the create() method defined in the CreateModelMixin. It will route PUT to update() in the UpdateModelMixin

The reason your code is creating new instances is because the default create() method is being called instead of your post() method. The correct way to do the update is to send it with the "PUT" method instead. This will be mapped to the update() method in UpdateModelMixin. Then override update.

Also, your router is going to create url patterns for you. It doesn't simply route everything through the same url because it will need a pk for updating and retrieving. The documentation on routers tells us that the PUT method is allowed at the following url:

{prefix}/{lookup}/

So in your case you need to be sending your request to '/api/cancelreservation/OBJECT_PK/'

here is what I would try.

The view:

class ReservationCancelView(mixins.RetrieveModelMixin,
                            mixins.ListModelMixin, mixins.DestroyModelMixin, mixins.CreateModelMixin,
                            mixins.UpdateModelMixin, viewsets.GenericViewSet):
    serializer_class = ReservationCSerializer
    permission_classes = (permissions.IsAuthenticated,)    
    queryset = Reservation.objects.all()

        def update(self, request, *args, **kwargs):
            # This retrieves the model instance by the pk in the url
            reservation = self.get_object()
            # request.data is a dictionary containing your data.
            # We copy it because you wanted to change 'reservedplaces' but it is immutable, and copying it makes it mutable
            data = request.data.copy()
            # This edits 'reservedplaces' before we initializes the serializer
            data['reservedplaces'] -= 1
            # This initializes the serializer
            serializer = self.get_serializer(reservation, data=data)
            # Always validate the data
            serializer.is_valid(raise_exception=True)
            # perform_update() will save the data to the database
            self.perform_update(serializer)
            # Return the JSON Response
            return Response(serializer.data)

The request:

let data = {
           'travel_id': rideID ,
           'id' : resID,
           'address' : address,
           'reservedplaces': nbplaces            
          };

$.ajax({
    method: 'PUT',
    url: '/api/cancelreservation/' + resID + '/',
    datatype: 'json',
    headers: {
        'Authorization': 'Token ' + localStorage.token
    },
    data: data,
    success: function (response) {
        console.log("Success!");
    }
})

I wasn't able to test the above code without seeing your model, but give it a shot and hopefully it works. If you need more help please post the Reservation model.

Upvotes: 1

Related Questions