I have the following model classes:
class Goods(models.Model):
name = models.CharField(max_length=100)
class InRecord(models.Model):
goods = models.ForeignKey(Goods, related_name='in_records')
timestamp = models.DateTimeField()
quantity = models.IntegerField()
class OutRecord(models.Model):
goods = models.ForeignKey(Goods, related_name='out_records')
timestamp = models.DateTimeField()
quantity = models.IntegerField()
So, I want to get a QuerySet which contains all the goods having a positive repository.
Another way to describe it, I want to filter Goods which has a greater InRecord quantity summary than OutRecord summary.
First, I use annotate
to add the summary to the queryset:
qs = Goods.objects.annotate(
qty_in=Sum(in_records__quantity),
qty_out=Sum(out_records_quantity)
)
This seemed works, but have one problem, when there is no relative in_records or out_records of some goods, the fields annotated returns None.
Question: So, is there any way for me to set a default in this case, just like a ifnull(max(inreocrd.quantity), 0)
* call in sql?
After this, I want to add a filter on that QuerySet:
I tried:
qs = qs.filter(qty_in__gt(F(qty_out)))
But still if there is no records on a goods, It doesn't work.
Please help.
Django allows using SQL subqueries.
F() expressions. An F() object represents the value of a model field, transformed value of a model field, or annotated column. It makes it possible to refer to model field values and perform database operations using them without actually having to pull them out of the database into Python memory.
to Django users. According to the documentation on models. OuterRef: It acts like an F expression except that the check to see if it refers to a valid field isn't made until the outer queryset is resolved.
When specifying the field to be aggregated in an aggregate function, Django will allow you to use the same double underscore notation that is used when referring to related fields in filters. Django will then handle any table joins that are required to retrieve and aggregate the related value.
You can use Django's Coalesce function. Something like this should work in Django 1.8 or later:
from django.db.models.functions import Coalesce
qs = Goods.objects.annotate(
qty_in=Sum(Coalesce(in_records__quantity, 0)),
qty_out=Sum(Coalesce(out_records__quantity, 0))
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With