我有两个定义如下的模型:
class House(models.Model):
# all the fields here
def capacity(self):
capacity = 0
for room in self.rooms.all():
capacity += room.capacity
return capacity
class Room(models.Model):
house = models.ForeignKey(
House,
on_delete=models.CASCADE,
related_name='rooms'
)
capacity = models.PositiveIntegerField(
default=1
)
我需要的是使用restframework中的所有数字查找(lt,lte,gt,gt,gte,range,exact)按容量过滤房屋,我这样做了:
import rest_framework_filters as filters
def capacity_filter(qs, name, value):
# filter implementation here
class HouseFilter(filters.FilterSet):
capacity = filters.NumberFilter(
method=capacity_filter
)
class Meta:
fields = ('capacity',)
class HouseViewSet(viewsets.ModelViewSet):
filter_class = HouseFilter
# other attrs here
它的工作原理只是为了确切的值,我不能使用__gt或__lt进行过滤,我尝试使用NumberFilter中的 lookup_expr 参数,但不能正常工作。
答案 0 :(得分:0)
drf_filters有一节:https://github.com/philipn/django-rest-framework-filters#allowing-any-lookup-type-on-a-field
答案 1 :(得分:0)
您可以使用partial来生成具有相应查找的可调用对象。例如,
def capacity_filter(qs, name, value, lookup_expr):
# implementation
class HouseFilter(filters.FilterSet):
capacity = filters.NumberFilter(
name='capacity',
method=partial(capacity_filter, lookup_expr='exact'))
capacity__lt = filters.NumberFilter(
name='capacity',
method=partial(capacity_filter, lookup_expr='lt'))
...
也就是说,您应该使用注释来计算房间容量,因为它将在数据库中而不是在内存中执行计算。这也可以让你放弃在这里使用method
参数。
# the query you want to construct
queryset = House.objects \
.annotate(capacity=Sum('rooms__capacity'))
.filter(...)
# filterset
class HouseFilter(FilterSet):
capacity = filters.NumberFilter(
name='capacity', lookup_expr='exact',
label='Capacity is equal to')
capacity__lt = filters.NumberFilter(
name='capacity', lookup_expr='lt',
label='Capacity is less than')
@property
def qs(self):
# Only annotate capacity if filtering by capacity
if not hasattr(self, '_qs') and self.form.is_valid() \
and any(f.startswith('capacity') for f in self.form.cleaned_data):
self.queryset = self.queryset \
.annotate(capacity=Sum('rooms__capacity'))
return super(HouseFilter, self).qs