Django-filter-过滤带注释的字段

问题描述 投票:0回答:1

我在django-tables2表上使用Django过滤器,我有一个自定义过滤器,该过滤器使用一个搜索框来搜索所有字段。 SiteFilterEx,它获取所有字段名称并创建或查询以搜索每个字段名称。

我的模型具有以下内容:

class Site(models.Model):
    location = models.CharField(max_length=50)
    ref = models.CharField(max_length=255, blank=True, null=True)
    bgp_as = models.CharField(max_length=6, verbose_name="BGP AS Number")
    opening_date = models.DateField(verbose_name="Site opening date", blank=True, null=True)
    tel = models.CharField(max_length=20, blank=True, null=True)
    address = models.CharField(max_length=255, blank=True, null=True)
    town = models.CharField(max_length=255, blank=True, null=True)
    postcode = models.CharField(max_length=10, blank=True, null=True)

但是,id还想搜索带注释的字段“ active_circuit”(可以在QuerySet中看到)但是,当我将其添加到字段列表中时,出现错误,指出它不存在。我需要以某种方式将带注释的字段作为有效字段传递给过滤器以进行搜索或其他?

过滤器:

class SiteFilterEx(django_filters.FilterSet):
    ex = django_filters.CharFilter(label='Ex filter', method='filter_ex')
    search_fields = ['location', 'sitesupernet__subnet', 'bgp_as', 'opening_date','town','postcode','active_circuit']

    def filter_ex(self, qs, name, value):
        if value:
            q_parts = value.split()

            # Use a global q_totals
            q_totals = Q()

            # This part will get us all possible segmantiation of the query parts and put it in the possibilities list
            combinatorics = itertools.product([True, False], repeat=len(q_parts) - 1)
            possibilities = []
            for combination in combinatorics:
                i = 0
                one_such_combination = [q_parts[i]]
                for slab in combination:
                    i += 1
                    if not slab: # there is a join
                        one_such_combination[-1] += ' ' + q_parts[i]
                    else:
                        one_such_combination += [q_parts[i]]
                possibilities.append(one_such_combination)

            # Now, for all possiblities we'll append all the Q objects using OR
            for p in possibilities:
                list1=self.search_fields
                list2=p
                perms = [zip(x,list2) for x in itertools.permutations(list1,len(list2))]

                for perm in perms:
                    q_part = Q()
                    for p in perm:
                        q_part = q_part & Q(**{p[0]+'__icontains': p[1]})
                    q_totals = q_totals | q_part

            qs = qs.filter(q_totals)
        return qs    

    class Meta:
        model = Site
        fields = ['ex']     
        form = SiteFilterForm  

视图:

class Sites(LoginRequiredMixin, ExportMixin, PagedFilteredTableView):
    model = Site
    table_class = SiteTable
    template_name = "app_settings/table_view.html"
    login_url = '/login/'
    redirect_field_name = 'redirect_to'
    filter_class = SiteFilterEx
    exclude_columns = ("buttons", )
    table_pagination = {'per_page': 12}

    def dispatch(self, *args, **kwargs):
        site_type = get_object_or_404(SiteType, pk=self.kwargs['site_type'])
        site_state = 'Open' if self.kwargs['state'] else 'Closed'
        self.site_type_name = '{} {}s'.format(site_state, site_type.site_type)
        self.site_type_icon = 'fa {}'.format(site_type.icon)
        return super(Sites, self).dispatch(*args, **kwargs)

    def get_queryset(self):
        site_type = self.kwargs['site_type']
        subnet = Subquery(
            DeviceCircuitSubnets.objects.filter(device__site_id=OuterRef('id'), \
                                        active_link=True, \
                                        circuit__decommissioned=False
                                        ).values('circuit__name')[:1])        
        active_circuit = Subquery(
            DeviceCircuitSubnets.objects.filter(device__site_id=OuterRef('id'), \
                                        active_link=True, \
                                        circuit__decommissioned=False
                                        ).values('circuit__name')[:1])

        return super(Sites, self).get_queryset().filter(
                is_live=self.kwargs['state'], site_type_id=site_type
            ).annotate(
                active_circuit=active_circuit
            ).prefetch_related('sitesupernet_set')


    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)     
        context['page_icon']=self.site_type_icon
        context['page_title']=self.site_type_name 
        return context

追踪错误:

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
  34.             response = get_response(request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  115.                 response = self.process_exception_by_middleware(e, request)

File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
  113.                 response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py" in view
  71.             return self.dispatch(request, *args, **kwargs)

File "/itapp/itapp/sites/views.py" in dispatch
  127.         return super(Sites, self).dispatch(*args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/contrib/auth/mixins.py" in dispatch
  52.         return super().dispatch(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/generic/base.py" in dispatch
  97.         return handler(request, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/views/generic/list.py" in get
  142.         self.object_list = self.get_queryset()

File "/itapp/itapp/sites/views.py" in get_queryset
  142.             return super(Sites, self).get_queryset().filter(

File "/itapp/itapp/itapp/functions.py" in get_queryset
  560.         return self.filter.qs

File "/usr/local/lib/python3.6/site-packages/django_filters/filterset.py" in qs
  237.                 qs = self.filter_queryset(qs)

File "/usr/local/lib/python3.6/site-packages/django_filters/filterset.py" in filter_queryset
  224.             queryset = self.filters[name].filter(queryset, value)

File "/usr/local/lib/python3.6/site-packages/django_filters/filters.py" in __call__
  765.         return self.method(qs, self.f.field_name, value)

File "/itapp/itapp/sites/filters.py" in filter_ex
  53.             qs = qs.filter(q_totals)

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in filter
  892.         return self._filter_or_exclude(False, *args, **kwargs)

File "/usr/local/lib/python3.6/site-packages/django/db/models/query.py" in _filter_or_exclude
  910.             clone.query.add_q(Q(*args, **kwargs))

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py" in add_q
  1290.         clause, _ = self._add_q(q_object, self.used_aliases)

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
  1312.                     current_negated, allow_joins, split_subq, simple_col)

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py" in _add_q
  1318.                     split_subq=split_subq, simple_col=simple_col,

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py" in build_filter
  1190.         lookups, parts, reffed_expression = self.solve_lookup_type(arg)

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py" in solve_lookup_type
  1049.         _, field, _, lookup_parts = self.names_to_path(lookup_splitted, self.get_meta())

File "/usr/local/lib/python3.6/site-packages/django/db/models/sql/query.py" in names_to_path
  1420.                                      "Choices are: %s" % (name, ", ".join(available)))

Exception Type: FieldError at /sites/sites/1/2/
Exception Value: Cannot resolve keyword 'active_circuit' into field. Choices are: acc_short, address,  device, downtimeschedule, id, is_live, last_hw_refresh_date, location, no_wallboard, opening_date, postcode, ref, site_type, site_type_id, sitecircuits, sitecontacts, sitefile, sitenotes, sitesupernet, snmpdata, tel, town, watchlist
django django-filter django-tables2
1个回答
0
投票

尝试使用查询集的aggregate方法代替annotateaggregate包含查询结果中的数据,这使得可以使用过滤器方法中的聚合字段,但annotate没有。聚合字段实际上表现为从数据库表中额外选择的值,并且也作为额外对象的字段包含在实体中。Difference between Django's annotate and aggregate methods?-在这里您可以找到一些说明

© www.soinside.com 2019 - 2024. All rights reserved.