I am using Django Filters package .
I define my filter in following way in the view
class UnitFilter(django_filters.FilterSet):
class Meta:
model = Unit
fields = [
'floor', 'number', 'building','lease','leaseterm',
'lease__is_active','lease__is_terminated','lease__is_renewed',]
My Unit Model on which I filter is following
class Unit(CommonInfo):
version = IntegerVersionField( )
number = models.CharField(max_length=30,null=True, blank=True)
max_occupants = models.PositiveSmallIntegerField()
floor = models.PositiveSmallIntegerField()
rooms = models.PositiveSmallIntegerField()
is_disabled_access = models.BooleanField(default=False)
balcony_quantity = models.PositiveSmallIntegerField()
building = models.ForeignKey(Building)
recomended_price = models.DecimalField(max_digits=7, decimal_places=2)
_lease = None
_leaseterm = None
#check = models.ManyToManyField(UnitCheck, through='UnitChecklist')
def _get_total(self):
from conditions.models import LeaseTerm
from lease.models import Lease
lease_dict = Lease.objects.filter(unit_id=self.id, is_active = True , is_terminated = False).aggregate(Max('id'))
if lease_dict['id__max']:
lease = lease_dict['id__max']
else:
lease = 0
leaseterm_dict = LeaseTerm.objects.filter(lease_id=lease, is_active = True , is_terminated = False).aggregate(Max('id'))
if leaseterm_dict['id__max']:
leaseterm = leaseterm_dict['id__max']
else:
leaseterm = 0
self._lease = lease
self._leaseterm = leaseterm
@property
def lease(self):
if self._lease is None:
self._get_total()
return self._lease
@property
def leaseterm(self):
if self._leaseterm is None:
self._get_total()
return self._leaseterm
There is 2 calculated properties in this model lease and leaseterm
lease property has no problem when leaseterm gives me this error
Meta.fields contains a field that isn't defined on this FilterSet: leaseterm
why? it it a bug in django-filter?Any work around?
See this for a good explanation.
When you do queryset.filter(field_name=field_value)
, Django translates that into a SQL query. Unfortunately, calculated properties only live on the Python object, so you can't filter by them.
The workaround is to, whenever you filter by one of these, include an annotation to your queryset that adds the proper field in SQL. The link has a good example of how to do this. It's harder than doing it in Python, but the only way to go really.