I am having issues with the performance of a couple of queries in my Django app... all others are very fast.
I have an Orders model with OrderItems, the query seems to be running much slower than other queries (1-2 seconds, vs. 0.2 seconds). I'm using MySQL backend. In the serializer I do a count to return whether an order has food or drink items, I suspect this is causing the performance hit. Is there a better way to do it?
Here is my models setup for Order and OrderItems
class Order(models.Model):
STATUS = (
('1', 'Placed'),
('2', 'Complete')
)
PAYMENT_STATUS = (
('1', 'Pending'),
('2', 'Paid'),
('3', 'Declined'),
('4', 'Manual')
)
shop= models.ForeignKey(Shop,on_delete=models.DO_NOTHING)
customer = models.ForeignKey(Customer,on_delete=models.DO_NOTHING)
total_price = models.DecimalField(max_digits=6, decimal_places=2,default=0)
created_at = models.DateTimeField(auto_now_add=True, null=True)
time_completed = models.DateTimeField(auto_now_add=True, null=True,blank=True)
time_cancelled = models.DateTimeField(auto_now_add=True, null=True,blank=True)
status = models.CharField(max_length=2, choices=STATUS, default='1',)
payment_method = models.CharField(max_length=2, choices=PAYMENT_METHOD, default='3',)
payment_status = models.CharField(max_length=2, choices=PAYMENT_STATUS, default='1',)
type = models.CharField(max_length=2, choices=TYPE, default='1',)
def __str__(self):
return str(self.id)
class OrderItem(models.Model):
order = models.ForeignKey(Order,on_delete=models.CASCADE)
type = models.CharField(max_length=200,default='DRINK')
drink = models.ForeignKey(
Drink,
blank=True,null=True,on_delete=models.DO_NOTHING
)
food = models.ForeignKey(
Food,
blank=True,
null=True,
on_delete=models.DO_NOTHING
)
quantity = models.IntegerField(blank=True,null=True)
price = models.DecimalField(max_digits=6, decimal_places=2,default=0)
created_at = models.DateTimeField(auto_now_add=True, null=True)
delivered = models.BooleanField(default=False)
def __str__(self):
return str(self.id)
In my rest order serializer, here is the query for get,
queryset = Order.objects.filter(shop=shop,status__in=['1','2'],payment_status__in=['2','4'])
The serializer is below, but this query is quite slow. I assume because I am doing a count() on OrderItems - is there a more efficient way to do this?
class OrderOverviewSerializer(serializers.ModelSerializer):
tabledetails = serializers.SerializerMethodField()
has_food = serializers.SerializerMethodField()
has_drink = serializers.SerializerMethodField()
class Meta:
model = Order
fields = ['id','total_price', 'created_at','has_food','has_drink','type','status','shop','table','customer','shopdetails']
def get_shopdetails(self, instance):
qs = Shop.objects.get(id=instance.shop.id)
serializer = ShopSerializer(instance=qs, many=False)
return serializer.data
def get_has_food(self, obj):
foodCount = OrderItem.objects.filter(order=obj.id,type='FOOD').count()
return foodCount
def get_has_drink(self, obj):
drinkCount = OrderItem.objects.filter(order=obj.id,type='DRINK').count()
return drinkCount