diff --git a/test_project/one_to_one/fixtures/one_to_one.json b/test_project/one_to_one/fixtures/one_to_one.json index b53f364..4e627f5 100644 --- a/test_project/one_to_one/fixtures/one_to_one.json +++ b/test_project/one_to_one/fixtures/one_to_one.json @@ -54,5 +54,12 @@ "name": "Steve" }, "pk": 3 +}, +{ + "model": "one_to_one.waiter", + "fields": { + "name": "Michal" + }, + "pk": 4 } ] diff --git a/test_project/one_to_one/models.py b/test_project/one_to_one/models.py index a2e4377..e0eb7f6 100644 --- a/test_project/one_to_one/models.py +++ b/test_project/one_to_one/models.py @@ -26,7 +26,7 @@ def __str__(self): @six.python_2_unicode_compatible class Waiter(models.Model): - restaurant = models.ForeignKey(Restaurant) + restaurant = models.ForeignKey(Restaurant, null=True) name = models.CharField(max_length=50) def __str__(self): diff --git a/tests/filtersets/test_base.py b/tests/filtersets/test_base.py index a41b118..397cfe3 100644 --- a/tests/filtersets/test_base.py +++ b/tests/filtersets/test_base.py @@ -231,3 +231,17 @@ def _test(fs, data, qs, expected, count): .exclude(name__icontains='jon')), 1 ) + _test( + WaiterFilterSet, + 'restaurant__isnull=True', + Waiter.objects.all(), + Waiter.objects.filter(restaurant__isnull=True), + 1 + ) + _test( + WaiterFilterSet, + 'restaurant__isnull=False', + Waiter.objects.all(), + Waiter.objects.filter(restaurant__isnull=False), + 3 + ) diff --git a/url_filter/filters.py b/url_filter/filters.py index b538594..7289a64 100644 --- a/url_filter/filters.py +++ b/url_filter/filters.py @@ -17,7 +17,7 @@ } LOOKUP_FIELD_OVERWRITES = { - 'isnull': forms.BooleanField(), + 'isnull': forms.BooleanField(required=False), 'second': forms.IntegerField(min_value=0, max_value=59), 'minute': forms.IntegerField(min_value=0, max_value=59), 'hour': forms.IntegerField(min_value=0, max_value=23), diff --git a/url_filter/filtersets/base.py b/url_filter/filtersets/base.py index 96d13e1..4a0f716 100644 --- a/url_filter/filtersets/base.py +++ b/url_filter/filtersets/base.py @@ -20,6 +20,10 @@ __all__ = ['FilterSet', 'FilterSetOptions', 'StrictMode'] +FK_FIELD_FILTERS = { + 'isnull', +} + class StrictMode(enum.Enum): """ @@ -154,6 +158,7 @@ def _init(self, data=None, queryset=None, context=None, self.queryset = queryset self.context = context or {} self.strict_mode = strict_mode + self._given_lookups = None def repr(self, prefix=''): header = '{name}()'.format(name=self.__class__.__name__) @@ -347,7 +352,10 @@ def get_spec(self, config): value = LookupConfig(config.key, config.data) if name not in self.filters: - raise SkipFilter + if name in FK_FIELD_FILTERS: + return super(FilterSet, self).get_spec(config) + else: + raise SkipFilter return self.filters[name].get_spec(value)