Просмотр исходного кода

Fixes #11539: Use BooleanFilter for 'empty' lookups (#11784)

* Use BooleanFilter for 'empty' lookups

* Always use BooleanFilter for 'empty' lookups

* Restore Empty lookup logic
Jeremy Stretch 2 лет назад
Родитель
Сommit
24a51dd86e
2 измененных файлов с 18 добавлено и 7 удалено
  1. 8 6
      netbox/extras/lookups.py
  2. 10 1
      netbox/netbox/filtersets.py

+ 8 - 6
netbox/extras/lookups.py

@@ -7,12 +7,14 @@ class Empty(Lookup):
     Filter on whether a string is empty.
     """
     lookup_name = 'empty'
-
-    def as_sql(self, qn, connection):
-        lhs, lhs_params = self.process_lhs(qn, connection)
-        rhs, rhs_params = self.process_rhs(qn, connection)
-        params = lhs_params + rhs_params
-        return 'CAST(LENGTH(%s) AS BOOLEAN) != %s' % (lhs, rhs), params
+    prepare_rhs = False
+
+    def as_sql(self, compiler, connection):
+        sql, params = compiler.compile(self.lhs)
+        if self.rhs:
+            return f"CAST(LENGTH({sql}) AS BOOLEAN) IS NOT TRUE", params
+        else:
+            return f"CAST(LENGTH({sql}) AS BOOLEAN) IS TRUE", params
 
 
 class NetContainsOrEquals(Lookup):

+ 10 - 1
netbox/netbox/filtersets.py

@@ -177,7 +177,8 @@ class BaseFilterSet(django_filters.FilterSet):
                     # create the new filter with the same type because there is no guarantee the defined type
                     # is the same as the default type for the field
                     resolve_field(field, lookup_expr)  # Will raise FieldLookupError if the lookup is invalid
-                    new_filter = type(existing_filter)(
+                    filter_cls = django_filters.BooleanFilter if lookup_expr == 'empty' else type(existing_filter)
+                    new_filter = filter_cls(
                         field_name=field_name,
                         lookup_expr=lookup_expr,
                         label=existing_filter.label,
@@ -224,6 +225,14 @@ class BaseFilterSet(django_filters.FilterSet):
 
         return filters
 
+    @classmethod
+    def filter_for_lookup(cls, field, lookup_type):
+
+        if lookup_type == 'empty':
+            return django_filters.BooleanFilter, {}
+
+        return super().filter_for_lookup(field, lookup_type)
+
 
 class ChangeLoggedModelFilterSet(BaseFilterSet):
     """