Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue with query filter on django.JSONField #1313

Closed
amirhoseinbidar opened this issue Jan 7, 2021 · 2 comments
Closed

issue with query filter on django.JSONField #1313

amirhoseinbidar opened this issue Jan 7, 2021 · 2 comments

Comments

@amirhoseinbidar
Copy link

django-filter can not filter on jsonField with NumberFilter

my situation is something like below desctiption

I have a model like this

class Product(model.Model):
    name = models.CharField(max_length=250)
    ....
    extra_data = models.JSONField(default=dict, null=True, blank=True)

assume some of extra_data always have something like { "size": 200 }

my filter is

class ProductFilter(FilterSet):
    extra_size = filters.NumberFilter(field_name="extra_data", lookup_expr="size")
    ....

when i call my end point (EXAMPLE: http://localhost:8001/api/products/rent/product/?extra_size=200) this error will raise

--some text--
.....
TypeError: Object of type Decimal is not JSON serializable

after some debug I found out this error is because NumberFilter turn income numbers to Decimal objects and jsonfield just
can not handle Decimal object

I am not sure this issue is yours or for JSONField but I will report same bug for JSONField

@amirhoseinbidar
Copy link
Author

amirhoseinbidar commented Jan 8, 2021

I found out this problem can solve with this way

from django_filters import filters
from django import forms


class IntegerFilter(filters.NumberFilter):
    field_class = forms.IntegerField


class FloatFilter(filters.NumberFilter):
    field_class = forms.FloatField


class IntegerRangeField(filters.RangeField):
    def __init__(self, fields=None, *args, **kwargs):
        if fields is None:
            fields = (
                forms.IntegerField(),
                forms.IntegerField())
        super().__init__(fields, *args, **kwargs)


class FloatRangeField(filters.RangeField):
    def __init__(self, fields=None, *args, **kwargs):
        if fields is None:
            fields = (
                forms.FloatField(),
                forms.FloatField())
        super().__init__(fields, *args, **kwargs)


class IntegerRangeFilter(filters.RangeFilter):
    field_class = IntegerRangeField


class FloatRangeFilter(filters.RangeFilter):
    field_class = FloatRangeField

and inside my filter

class ProductFilter(FilterSet):
    extra_size = filters.IntegerFilter(field_name="extra_data", lookup_expr="size")

I thing it is good idea add this solution to your document

@carltongibson
Copy link
Owner

Thanks @amirhoseinbidar — I’m going to mark this a duplicate of #1298

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants