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 Jan 8, 2020
1 parent e6d5f2d commit 12c6281
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 0 deletions.
5 changes: 5 additions & 0 deletions django_filters/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from datetime import timedelta

from django import forms
from django.contrib.postgres.forms import JSONField
from django.db.models import Q
from django.db.models.constants import LOOKUP_SEP
from django.forms.utils import pretty_name
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()
3 changes: 3 additions & 0 deletions django_filters/filterset.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
ManyToOneRel,
OneToOneRel
)
from django.contrib.postgres.fields import JSONField

from .conf import settings
from .constants import ALL_FIELDS
Expand All @@ -22,6 +23,7 @@
DateTimeFilter,
DurationFilter,
Filter,
JSONFilter,
ModelChoiceFilter,
ModelMultipleChoiceFilter,
NumberFilter,
Expand Down Expand Up @@ -130,6 +132,7 @@ def get_declared_filters(cls, bases, attrs):
models.GenericIPAddressField: {'filter_class': CharFilter},
models.CommaSeparatedIntegerField: {'filter_class': CharFilter},
models.UUIDField: {'filter_class': UUIDFilter},
JSONField: {'filter_class': JSONFilter},

# Forward relationships
models.OneToOneField: {
Expand Down
4 changes: 4 additions & 0 deletions docs/ref/filters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ Matches on a time. Used with ``TimeField`` by default.

Matches on a date and time. Used with ``DateTimeField`` by default.

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

Matches a json value, used with ``JSONfield`` by default.

``IsoDateTimeFilter``
~~~~~~~~~~~~~~~~~~~~~
Expand Down
2 changes: 2 additions & 0 deletions tests/models.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from django import forms
from django.contrib.postgres.fields import JSONField
from django.db import models
from django.utils.translation import gettext_lazy as _

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
23 changes: 23 additions & 0 deletions tests/test_filtering.py
Original file line number Diff line number Diff line change
Expand Up @@ -1990,3 +1990,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)
10 changes: 10 additions & 0 deletions 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 @@ -34,6 +35,7 @@
DurationFilter,
Filter,
IsoDateTimeFromToRangeFilter,
JSONFilter,
LookupChoiceFilter,
ModelChoiceFilter,
ModelMultipleChoiceFilter,
Expand Down Expand Up @@ -1593,3 +1595,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 12c6281

Please sign in to comment.