Martian4x
Martian4x

Reputation: 47

Django Serializer Passing a arguments into model function

New to Django and DRF, I have a method in the model properties which accept arguments. I have managed to call it successful though a serializer class with default paramenters and getting a JSON response. My problem is I can't pass argument to that function named balance. I have successful pass my argument from view to serializer class but from serializer to model that where I have failed. I thought will be appreciated.

model.py

class Item(models.Model):
   entered_by = models.ForeignKey(User, on_delete=models.PROTECT)
   name = models.CharField(max_length=50, blank=True)

   @property
   def balance(self, stock_type='Retail'):
      stock = Stock.objects.filter(item=self, type=stock_type, status='InStock').aggregate(models.Sum('quantity')).get('quantity__sum')
      return stock or 0

views.py

def getItemInfo(request):
   if request.is_ajax and request.method == "GET":
      id = request.GET.get("item_id", None)
      sell_type = request.GET.get("sell_type", None)
      item = Item.objects.get(id=id)
      if item:
         serializer = ItemSerializer(item, context={'sell_type':sell_type})
         return JsonResponse(serializer.data, status = 200, safe=False)
      else:
         return JsonResponse({"data":False}, status = 400)

serializer.py

from rest_framework import serializers
from .models import Item

class ItemSerializer(serializers.ModelSerializer):
   balance = serializers.SerializerMethodField()

   class Meta:
      model = Item
      fields = ('entered_by', 'name', 'balance', 'sell_mode')
   
   def get_balance(self, object):
      sell_type = self.context.get("sell_type")
      if sell_type:
         return object.balance(sell_type)
      return object.balance

The error I'm getting 'int' object is not callable

Upvotes: 1

Views: 3005

Answers (1)

Jiho Lee
Jiho Lee

Reputation: 987

@property couldn't be called. So I made member variable and setter (with calculation) methods in Item model, then make sure setter method will be called in get_balance serializer method, just before returning balance.

Django ORM model itself is just a class; you can do anything class could, not just only linking with ORM.

My Code:

models.py

from django.db import models
from django.contrib.auth.models import User

class Item(models.Model):
   entered_by = models.ForeignKey(User, on_delete=models.PROTECT)
   name = models.CharField(max_length=50, blank=True)

   _balance = 0

   def calculate_balance(self, stock_type='Retail'):
      stock = Stock.objects.filter(item=self, type=stock_type, status='InStock').aggregate(
          models.Sum('quantity')).get('quantity__sum')
      self._balance = stock or 0

   @property
   def balance(self):
      return self._balance

serializer.py

from django.contrib.auth.models import User
from rest_framework import serializers
from .models import Item


class ItemSerializer(serializers.ModelSerializer):
   balance = serializers.SerializerMethodField()

   class Meta:
      model = Item
      fields = ('entered_by', 'name', 'balance')

   def get_balance(self, object):
      sell_type = self.context.get("sell_type")
      if sell_type:
          object.calculate_balance(sell_type)
      return object.balance

views.py

from .models import Item
from .serializer import ItemSerializer
from django.http.response import JsonResponse

def getItemInfo(request):
    if request.is_ajax and request.method == "GET":
        id = request.GET.get("item_id", None)
        if id is None:
            return JsonResponse({"data": False}, status=400)
        sell_type = request.GET.get("sell_type", None)
        try:
            item = Item.objects.get(id=id)
            serializer = ItemSerializer(item, context={'sell_type': sell_type})
            return JsonResponse(serializer.data, status=200, safe=False)
        except Item.DoesNotExist:
            return JsonResponse({"data": False}, status=400)

Upvotes: 3

Related Questions