2017-09-14 94 views
0

我已经两个模型这样定义:具有多个查找的Django RestFramework方法滤波器

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 
    ) 

我需要的是过滤使用所有号码查找(LT,LTE,GT,GTE通过其容量的房屋,范围,完全)在restframework,我这样做:

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,我试图与lookup_expr parametter在NumberFilter但不起作用。

回答

0

你可以使用一个部分来生成相应的查找一个可调用。例如,

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 
相关问题