Skip to content

Commit

Permalink
✨ Add JSONFilter
Browse files Browse the repository at this point in the history
Make to work with postgre JSONField
  • Loading branch information
sGeeK44 committed Sep 20, 2019
1 parent da4b64e commit dcdf4ec
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 3 deletions.
5 changes: 5 additions & 0 deletions django_filters/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from django.utils.itercompat import is_iterable
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
from django.contrib.postgres.forms import JSONField

from .conf import settings
from .constants import EMPTY_VALUES
Expand Down Expand Up @@ -788,3 +789,7 @@ def method(self):
(parent.__class__.__module__, parent.__class__.__name__, instance.method)

return method


class JSONFilter(Filter):
field_class = JSONField()
4 changes: 3 additions & 1 deletion django_filters/filterset.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
ModelMultipleChoiceFilter,
NumberFilter,
TimeFilter,
UUIDFilter
UUIDFilter,
JSONFilter,
)
from .utils import (
get_all_model_fields,
Expand Down Expand Up @@ -130,6 +131,7 @@ def get_declared_filters(cls, bases, attrs):
models.GenericIPAddressField: {'filter_class': CharFilter},
models.CommaSeparatedIntegerField: {'filter_class': CharFilter},
models.UUIDField: {'filter_class': UUIDFilter},
models.JSONField: {'filter_class': JSONFilter},

# Forward relationships
models.OneToOneField: {
Expand Down
6 changes: 6 additions & 0 deletions docs/ref/filters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -828,3 +828,9 @@ If you wish to sort by non-model fields, you'll need to add custom handling to a
return ...

return super(CustomOrderingFilter, self).filter(qs, value)


``JSONFilter``
~~~~~~~~~~~~~~

This filter matches JSON values, used with ``models.JSONField`` by default.
2 changes: 2 additions & 0 deletions tests/models.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from django import forms
from django.db import models
from django.contrib.postgres.fields import JSONField
from django.utils.translation import gettext_lazy as _

REGULAR = 0
Expand Down Expand Up @@ -102,6 +103,7 @@ class Book(models.Model):
title = models.CharField(max_length=100)
price = models.DecimalField(max_digits=6, decimal_places=2)
average_rating = models.FloatField()
meta = JSONField()

def __str__(self):
return self.title
Expand Down
26 changes: 25 additions & 1 deletion tests/test_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
OrderingFilter,
RangeFilter,
TimeRangeFilter,
TypedMultipleChoiceFilter
TypedMultipleChoiceFilter,
JSONFilter,
)
from django_filters.filterset import FilterSet

Expand Down Expand Up @@ -1990,3 +1991,26 @@ class Meta:
f = F({'status': '2'}, queryset=qs)
self.assertEqual(len(f.qs), 2)
self.assertEqual(f.qs.count(), 2)


class JSONFilterTests(TestCase):

def test_filtering(self):
b1 = Book.objects.create(
title="Ender's Game", price='1.00', average_rating=3.0, meta={tag: 1})
b2 = Book.objects.create(
title="Rainbow Six", price='1.00', average_rating=3.0, meta={tag: 2})
b3 = Book.objects.create(
title="Snowcrash", price='1.00', average_rating=3.0, meta={tag2: 2})

class F(FilterSet):
class Meta:
model = Book
fields = ['meta']

qs = Book.objects.all()
f = F(queryset=qs)
self.assertQuerysetEqual(f.qs, [b1.pk, b2.pk, b3.pk],
lambda o: o.pk, ordered=False)
f = F({'meta__tag': 2}, queryset=qs)
self.assertQuerysetEqual(f.qs, [b2.pk], lambda o: o.pk)
12 changes: 11 additions & 1 deletion tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from django.test import TestCase, override_settings
from django.utils import translation
from django.utils.translation import gettext as _
from django.contrib.postgres.forms import JSONField

from django_filters import filters, widgets
from django_filters.fields import (
Expand Down Expand Up @@ -45,7 +46,8 @@
TimeFilter,
TimeRangeFilter,
TypedMultipleChoiceFilter,
UUIDFilter
UUIDFilter,
JSON,
)
from tests.models import Book, User

Expand Down Expand Up @@ -1588,3 +1590,11 @@ def test_help_text(self):
# regression test for #756 - the ususal CSV help_text is not relevant to ordering filters.
self.assertEqual(OrderingFilter().field.help_text, '')
self.assertEqual(OrderingFilter(help_text='a').field.help_text, 'a')


class JSONFilterTests(TestCase):

def test_default_field(self):
f = JSONFilter()
field = f.field
self.assertIsInstance(field, JSONField)

0 comments on commit dcdf4ec

Please sign in to comment.