Reynold Bhatia
Reynold Bhatia

Reputation: 139

Auto calculation on a field in a model in Django RESTframework

So I have a model which has an attribute to be auto calculated when the api receives a POST request. The model is a bill model where the totalpayment is calculated on numberOfHours * paymentRate. Django does not allow me to do so by setting default value. Is there a way to do this?

Model

class Bill(models.Model):
    billID = models.AutoField(primary_key=True)
    bill_dt = models.DateField()
    hours =  models.FloatField()
    workAssignmentID_fk = models.ForeignKey(WorkAssignment, null=True, default=None)
    totalPayment = models.FloatField(default=0)

    def __unicode__(self):
        return u'%s' % (self.bill_dt)

    def __str__(self):
        return u'%s' % (self.bill_dt)

Serializer

class ReadBillSerializer(serializers.HyperlinkedModelSerializer):
    workAssignmentID_fk = ReadWorkAssignmentSerializer()

    class Meta:
        model = Bill
        fields = ('url', 'bill_dt', 'hours', 'workAssignmentID_fk', 'totalPayment')

class WriteBillSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Bill
        fields = ('url', 'bill_dt', 'hours', 'workAssignmentID_fk', 'totalPayment')

View

class BillViewSet(viewsets.ModelViewSet):
    queryset = Bill.objects.all()

    def get_serializer_class(self, *args, **kwargs):        
        if self.request.method == 'POST' or self.request.method == 'PUT':
            return WriteBillSerializer
        return ReadBillSerializer

In the model Bill, I want totalPayment = hours * workAssignmentID_fk.paymentRate.

paymentRate is an attribute in the workAssignmentID_fk.

Upvotes: 2

Views: 2946

Answers (1)

Rahul Gupta
Rahul Gupta

Reputation: 47876

You can override perform_create() function in your view and pass the value of totalPayment to the save() method of serializer.

perform_create() is called when saving a new object instance. You can use this object creation hook.

class BillViewSet(viewsets.ModelViewSet):
    queryset = Bill.objects.all()

    def get_serializer_class(self, *args, **kwargs):        
        if self.request.method == 'POST' or self.request.method == 'PUT':
            return WriteBillSerializer
        return ReadBillSerializer

    def perform_create(self, serializer):
        hours = serializer.validated_data['hours'] # get the value of hours
        work_assignment_object = <get_the_workAssignmentID_fk_object_from_passed_url>
        payment_rate = work_assignment_object.paymentRate # get the value of 'paymentRate' from work assignment object
        total_payment = hours*payment_rate # calculate value of total payment
        serializer.save(total_payment=total_payment, workAssignmentID_fk=work_assignment_object) # pass the value of total payment to be saved and the work assignment object

Upvotes: 3

Related Questions