philipn / django-rest-framework-filters Goto Github PK
View Code? Open in Web Editor NEWBetter filtering for Django REST Framework
License: Other
Better filtering for Django REST Framework
License: Other
Now that django-filter has an active maintainer I don't see a reason why it shouldn't be reviewed and accepted.
I have a rest_framework_filters.FilterSet
-derived class which works perfectly for filtering but it doesn't show any field filters in the browsable API.
I've been scouring the web for information about this but just can't find anything. Is it a known limitation that I somehow missed, or is it a bug? Maybe related to #40 (Use new DRF-friendly FilterSet & Backend)?
Hi @philipn - could you review and release v0.8.0 to pypi? This brings drf-filters up-to-date with the recent django-filter 0.13.0 release
Changelog:
v0.8.0
------
This release is tied to a major update of django-filter (more details in #66),
which fixes how lookup expressions are resolved. 'in', 'range', and 'isnull'
lookups no longer require special handling by django-rest-framework-filters.
This has the following effects:
* Deprecates ArrayDecimalField/InSetNumberFilter
* Deprecates ArrayCharField/InSetCharFilter
* Deprecates FilterSet.fix_filter_field
* Deprecates ALL_LOOKUPS in favor of '__all__' constant.
* AllLookupsFilter now generates only valid lookup expressions.
* #2 'range' lookup types do not work
* #15 Date lookup types do not work (year, day, ...)
* #16 'in' lookup types do not work
* #64 Fix browsable API filter form
* #69 Fix compatibility with base django-filter `FilterSet`s
* #70 Refactor related filter handling, fixing some edge cases
* Deprecated 'cache' argument to FilterSet
* #73 Warn use of `order_by`
You mention this in "wanted functionality"
Is this still planned?
And is there a best practice to achieve OR functionality?
Hi
I have seen that your Django version is 1.8+ though with Django 1.9.7 I get the following error message:
rest_framework_filters/filterset.py", line 12, in
from django.utils.datastructures import SortedDict
ImportError: cannot import name 'SortedDict'
Can you please fix that?
Is there any documentation of the library with a full changelog between releases?
Hello,
Imagine this very simple example of Dogs that have Human enemies and Human friends:
model Human:
name: CharField()
model Dog:
friends: ManyToMany(Human)
enemies: ManytToMany(Human)
filter DogFilter:
friends: Filter(name="friends")
enemies: Filter(name="ennemies")
When I hit the API the filter class performs a duplicated query select all Humans
one time for the field friends
another time for the field enemies
.
I have two questions:
1. is it possible to cache a duplicated query?
2. Why does these queries happen even when I do not filter at all in the API?
Let me know if you need more clarification.
In Django 1.9+, using AllLookupsFilter
on a related field will use the incorrect set of lookups. It seems to use the lookups of the underlying AutoField instead of the lookups for the ForeignKey. For example, changing the test NoteFilterWIthAll
FilterSet to:
class NoteFilterWithAll(FilterSet):
title = AllLookupsFilter(name='title')
author = AllLookupsFilter()
class Meta:
model = Note
Raises this error:
ImportError: Failed to import test module: tests.test_filterset
Traceback (most recent call last):
File "lib/python2.7/unittest/loader.py", line 254, in _find_tests
module = self._get_module_from_name(name)
File "lib/python2.7/unittest/loader.py", line 232, in _get_module_from_name
__import__(name)
File "tests/test_regressions.py", line 25, in <module>
from .testapp.filters import (
File "tests/testapp/filters.py", line 20, in <module>
class NoteFilterWithAll(FilterSet):
File "rest_framework_filters/filterset.py", line 67, in __new__
f = new_class.filter_for_field(field, filter_.name, lookup_expr)
File ".env/lib/python2.7/site-packages/django_filters/filterset.py", line 422, in filter_for_field
f, lookup_type = resolve_field(f, lookup_expr)
File ".env/lib/python2.7/site-packages/django_filters/utils.py", line 87, in resolve_field
final_lookup = lhs.get_lookup(name)
File ".env/lib/python2.7/site-packages/django/db/models/expressions.py", line 291, in get_lookup
return self.output_field.get_lookup(lookup)
File ".env/lib/python2.7/site-packages/django/db/models/fields/related.py", line 693, in get_lookup
raise TypeError('Related Field got invalid lookup: %s' % lookup_name)
TypeError: Related Field got invalid lookup: regex
Python 3.5 introduces a new implementation of OrderedDict in C.
A test in my project started failing after I upgraded from python 3.4 to 3.5 with RuntimeError: OrderedDict mutated during iteration
, so I decided to clone django-rest-framework-filters and run the tests using python 3.5.
Six of them failed with the same RuntimeError
. Some other tests had failed assertions. When I run the tests on the same machine but with Python 3.4 all the tests pass.
In the ORM you could do:
>>> Beer.objects.exclude(vendor__name__icontains='Busch').filter(...)
It would be awesome to replicate this functionality here. Perhaps prefacing the filter with __exclude
ie:
http://some.serv.e.r/api/beers/?exclude__name__icontains='bud'
I was wondering whether there's a way to apply a FilterSet to a non-generic API View and Django model - i.e. to just apply parsing of GET based filters?
e.g.
# View
class AbstractAPIView(APIView):
def get(self, request, *args, **kwargs):
filters = self.get_filters(self.request.query_params)
custom_api.get_non_model_instances(from_date=filters.from_date)
# Filterset
class AbstractFilterset(filters.Filterset):
from_date = filters.DateFilter()
# /endpoint?from_date=2016-01-01
Where the filterset could just be used to parse the query params, but not be applied to a queryset?
This datetime does not seem to parse correctly: 2010-1-2T23:18:23.861723Z
even though DRF handles the format.
See also: http://www.django-rest-framework.org/api-guide/fields/#datetimefield
I sometimes get errors stemming from the return value in the filter_queryset()
method of rest_framework_filters.backends.DjangoFilterBackend
. If I switch to using rest_framework.filters.DjangoFilterBackend
things work fine. I'm having a hard time quantifying it beyond that but here are two snippets of tracebacks that might give some context.
This is the more common one:
File "/home/vagrant/venv/lib/python2.7/site-packages/rest_framework_filters/backends.py" in filter_queryset
48. return _filter.qs
File "/home/vagrant/venv/lib/python2.7/site-packages/django_filters/filterset.py" in qs
314. value = self.form.cleaned_data[name]
Exception Type: AttributeError at /esdb_api/v1/contact/
Exception Value: 'ContactFilterForm' object has no attribute 'cleaned_data'
I also see this traceback, but note that I am not using any filters in the request that generated this traceback:
File "/home/vagrant/venv/lib/python2.7/site-packages/rest_framework_filters/backends.py" in filter_queryset
48. return _filter.qs
File "/home/vagrant/venv/lib/python2.7/site-packages/django_filters/filterset.py" in qs
314. value = self.form.cleaned_data[name]
Exception Type: KeyError at /esdb_api/v1/contact/
Exception Value: u'location__consoles__lt'
neither /myapi/articles/?tags__contains=Tag 1&tags__contains=Tag 2
nor /myapi/articles/?tags__icontains=Tag 1&tags__icontains=Tag 2
works
/myapi/articles/?tags__contains=Tag 1&tags__icontains=Tag 2
works however
I can't seem to find a changelog - either in the readme, as a separate file in the repo or detailed at https://github.com/philipn/django-rest-framework-filters/releases
Please could we add one? :-)
I have a database of judges each of whom have degrees from specific schools.
I want to use my API to either query judges that went to a specific school:
/api/judges/?educations__school_name=vanderbilt
Or I want to filter which judges went to a specific school:
/api/schools/?judges__race=black
I can set up a RelatedFilter
on one of these, but when I set it up on the second one, it can't find the class.
This problem is handled in Django models by allowing strings for ForeignKey names:
appointer = models.ForeignKey(
'Politician',
)
Is there a way to do this with Django filters?
Thanks for the great package.
C/o @slafs, carltongibson/django-filter#162 will probably simplify our code here.
can i use __in for multiple filters ?
A current limitation is that you cannot use AllLookupsFilter
in conjunction with RelatedFilter
. The following obviously does not work, as the declared filters will overwrite each other:
class FooFilter(FilterSet):
bar = RelatedFilter()
bar = AllLookupsFilter()
class Meta:
model = Foo
You cannot use the '__all__'
shortcut for the dict-style syntax either, as it's just a shorthand for the declarative style above.
edit: the next release of django-filter will allow '__all__'
to be reimplemented, solving a couple of issues. This still doesn't fix the declarative case though.
A workaround is to use the dict-style syntax without '__all__'
. eg,
class FooFilter(FilterSet):
bar = RelatedFilter()
class Meta:
model = Foo
fields = {
'bar': ['exact', 'lt', 'gt'],
}
Including 'exact' does not matter here, as generated filters will not overwrite declared filters (which would be the RelatedFilter
in this case.
We could add a RelatedAllFilter
, AllLookupsRelatedFilter
, AllLookupsWithRelatedFilter
, or something along those lines that combines the behavior of both AllLookupsFilter and RelatedFilter.
Hi, I'm using django-rest-framework-filters in my project, and it works quite well for some of my models which has FK & M2M. However, it doesn't work for some other models and I've posted a question on stackoverflow:
http://stackoverflow.com/questions/28247920/djangofilterbackend-not-working-with-my-models-manytomany
This seems quite a strange error. Many thanks!
This turns out to be a simple solution. thanks!
I'm guessing it's required? However - it confused me at first that it wasn't listed.
Hi !
cf https://docs.djangoproject.com/en/1.9/topics/db/models/#abstract-base-classes
Is there an equivalent for FilterSets ?
When I do:
class FilterMixin(FilterSet):
common_field = AllLookupsFilter('field_name')
# no possibility to do:
# class Meta:
# abstract = True
class ActualFilter(FilterMixin, FilterSet):
# other filters
class Meta:
model = MyModel
I get an error :
File "rest_framework_filters/filterset.py", line 57, in __new__
field = filterset.get_model_field(model, filter_.name)
If I do class FilterMixin(object): ..
, the common filters are not detected.
I would really like not having to repeat the fields multiple times !
Thanks !
Can you show an example that uses fieldname__range
? After trying some things myself, googling and browsing source code of this project and django-filter
I've come up empty handed.
2015-02-10 format,__year failure
Django REST Framework says that When using boolean fields, you should use the values True and False in the URL query parameters, rather than 0, 1, true or false.
This cannot be achieved with django-rest-framework-filters. Must use 0 or 1 for boolean field filtering. True and False doesn't work.
Traceback (most recent call last):
File "", line 1, in
File "/usr/local/lib/python2.7/site-packages/rest_framework_filters/init.py", line 3, in
from .filterset import FilterSet
File "/usr/local/lib/python2.7/site-packages/rest_framework_filters/filterset.py", line 13, in
from django_filters import filterset
File "/usr/local/lib/python2.7/site-packages/django_filters/init.py", line 3, in
from .filterset import FilterSet
File "/usr/local/lib/python2.7/site-packages/django_filters/filterset.py", line 19, in
from .filters import (Filter, CharFilter, BooleanFilter, BaseInFilter, BaseRangeFilter,
File "/usr/local/lib/python2.7/site-packages/django_filters/filters.py", line 16, in
from .fields import (
File "/usr/local/lib/python2.7/site-packages/django_filters/fields.py", line 13, in
from .utils import handle_timezone
File "/usr/local/lib/python2.7/site-packages/django_filters/utils.py", line 4, in
from django.db.models.expressions import Expression
ImportError: cannot import name Expression
Just an FYI - I couldn't find any django version restrictions in your release notes.
Cheers.
My /api/articles/
returns 100 results.
Both /api/articles/title__contains=Hot
and /api/articles/title__icontains
return 100 results.
Negation is working.
Exact match is working.
My ViewSet is as follows:
import rest_framework_filters as rf_filters
from rest_framework import filters
class ArticleFilterRf(rf_filters.FilterSet):
category = rf_filters.CharFilter(name="cat__slug")
category_id = rf_filters.CharFilter(name="cat_id")
class Meta:
model = Article
fields = ['id', 'status', 'category', 'category_id', 'deleted', 'author', 'featured', 'tags', 'title']
class ArticleViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing user instances.
"""
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
serializer_class = ArticleSerializer
queryset = Article.objects.all()
filter_backends = (filters.SearchFilter, filters.DjangoFilterBackend, filters.OrderingFilter,)
search_fields = ('title', 'tags', 'slug', 'status', 'cat__title', 'cat__slug', 'author')
filter_class = ArticleFilterRf
ordering_fields = ('title', 'updated')
ordering = ('updated',)
Attempting to filter on a non-existent field of a related filter will cause cache_key()
method to attempt to sort on a NoneType value causing an exception.
Problematic line here
Example stack trace:
Traceback:
File "/usr/local/lib/python3.4/dist-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.4/dist-packages/django/views/decorators/csrf.py" in wrapped_view
58. return view_func(*args, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/rest_framework/viewsets.py" in view
87. return self.dispatch(request, *args, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/rest_framework/views.py" in dispatch
466. response = self.handle_exception(exc)
File "/usr/local/lib/python3.4/dist-packages/rest_framework/views.py" in dispatch
463. response = handler(request, *args, **kwargs)
File "/usr/local/lib/python3.4/dist-packages/rest_framework_expander/views.py" in list
53. queryset = self.filter_queryset(self.get_queryset())
File "/usr/local/lib/python3.4/dist-packages/rest_framework/generics.py" in filter_queryset
151. queryset = backend().filter_queryset(self.request, queryset, self)
File "/usr/local/lib/python3.4/dist-packages/rest_framework_filters/backends.py" in filter_queryset
15. return filter_class(request.query_params, queryset=queryset, cache=cache).qs
File "/usr/local/lib/python3.4/dist-packages/rest_framework_filters/filterset.py" in qs
174. requested_filters = self.get_filters()
File "/usr/local/lib/python3.4/dist-packages/rest_framework_filters/filterset.py" in get_filters
124. key = self.cache_key(filterset_class, filter_names)
File "/usr/local/lib/python3.4/dist-packages/rest_framework_filters/filterset.py" in cache_key
163. return '%sSubset-%s' % (filterset.__name__, '-'.join(sorted(filter_names)), )
Exception Type: TypeError at /v0.7/posts/
Exception Value: sequence item 0: expected str instance, NoneType found
It seems like this test case should pass:
diff --git a/tests/test_backends.py b/tests/test_backends.py
index 1394e3a..88fb8d3 100644
--- a/tests/test_backends.py
+++ b/tests/test_backends.py
@@ -16,3 +16,14 @@ class BackendTest(APITestCase):
self.assertEqual(len(response.data), 1)
self.assertEqual(response.data[0]['username'], 'user1')
+
+ def test_django_filter_compatibility_twice(self):
+ response = self.client.get('/dffield-users/', {'username': 'user1'}, content_type='json')
+
+ self.assertEqual(len(response.data), 1)
+ self.assertEqual(response.data[0]['username'], 'user1')
+
+ response = self.client.get('/dffield-users/', {'username': 'user1'}, content_type='json')
+
+ self.assertEqual(len(response.data), 1)
+ self.assertEqual(response.data[0]['username'], 'user1')
diff --git a/tests/testapp/urls.py b/tests/testapp/urls.py
index 23e87ba..5f7b405 100644
--- a/tests/testapp/urls.py
+++ b/tests/testapp/urls.py
@@ -7,6 +7,7 @@ from . import views
router = routers.DefaultRouter()
router.register(r'df-users', views.DFUserViewSet, base_name='df-users')
+router.register(r'dffield-users', views.DFFieldUserViewSet, base_name='dffield-users')
router.register(r'users', views.UserViewSet,)
router.register(r'notes', views.NoteViewSet,)
diff --git a/tests/testapp/views.py b/tests/testapp/views.py
index 7e3956f..75761a0 100644
--- a/tests/testapp/views.py
+++ b/tests/testapp/views.py
@@ -16,6 +16,17 @@ class DFUserViewSet(viewsets.ModelViewSet):
filter_class = DFUserFilter
+class DFFieldUserViewSet(viewsets.ModelViewSet):
+ # used to test compatibility with the drf-filters backend
+ # with standard django-filter FilterSets.
+ queryset = User.objects.all()
+ serializer_class = UserSerializer
+ filter_backends = (backends.DjangoFilterBackend, )
+ filter_fields = {
+ 'username': '__all__'
+ }
+
+
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
But it fails on the second get
. It looks like the generation of fields runs through and deletes the Meta.fields which is a reference to the underlying filter_fields
which are then deleted.
On the second API call, the get_filter_class
will return None
because there are no filter_fields
or filter_class
causing no filtering to be applied.
I tried with
class ContainerChainedFilter(ChainedFilterSet):
estimate_time = AllLookupsFilter(name='estimate_time')
step = AllLookupsFilter(name='step')
class Meta:
model = ContainerSession
fields = ['estimate_time', 'step']
step work with step__gte, step__gt, step__lt, step__lte.... but not work with
step__isnull=True, step__isnull=False, step__isnull=1, step__isnull=0...
Every lookup type work except isnull
Django==1.8.3
djangorestframework-filters==0.5.0
django-filter==0.10.0
python Version 2.7.6
I added the library to my INSTALLED APPS but when i try to run the app , it throws me the following error:
Traceback (most recent call last):
File "manage.py", line 13, in <module>
execute_from_command_line(sys.argv)
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/django/core/management/__init__.py", line 338, in execute_from_command_line
utility.execute()
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/django/core/management/__init__.py", line 312, in execute
django.setup()
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/django/__init__.py", line 18, in setup
apps.populate(settings.INSTALLED_APPS)
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/django/apps/registry.py", line 85, in populate
app_config = AppConfig.create(entry)
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/django/apps/config.py", line 86, in create
module = import_module(entry)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/importlib/__init__.py", line 37, in import_module
__import__(name)
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/rest_framework_filters/__init__.py", line 3, in <module>
from .filterset import FilterSet
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/rest_framework_filters/filterset.py", line 52, in <module>
class FilterSet(six.with_metaclass(FilterSetMetaclass, filterset.FilterSet)):
File "/Users/ronsuez/.virtualenvs/lims/lib/python2.7/site-packages/rest_framework_filters/filterset.py", line 58, in FilterSet
'filter_class': filters.IsoDateTimeFilter,
AttributeError: 'module' object has no attribute 'IsoDateTimeFilter'
was searching in the django-filter-docs and they have that filter defined , but the package cannot found it
Given the following filterset,
class F(FilterSet):
email = filters.CharFilter()
class Meta:
model = User
fields = {'email: '__all__'}
There are a few problems:
AllLookupsFilter
will be created that overwrites the existing CharFilter
for email
. Declared filters should have precedence over Meta.fileds
.Meta.fields
was "The Wrong Thing To Do" apparently, even though it 'works'. If a user inspects the fields dict, it is confusing when the key is no longer present. We need to hook into filters_for_model
for a proper solution. There was also #81, but that was solved by copying the dict.Todo:
filters_for_model
to reimplement __all__
handling.FilterSet.convert__all__()
and FilterBackend.get_filter_class()
. Deprecations aren't necessary as convert__all__
is an internal method and get_filter_class
does not modify the default behavior.The lookup type in
is supported for CharField and NumberFiled though if a choices
argument is passed to the field it won't work.
See fix_filter_field is using a condition on the type of f
@classmethod
def fix_filter_field(cls, f):
"""
Fix the filter field based on the lookup type.
"""
lookup_type = f.lookup_type
if lookup_type == 'isnull':
return filters.BooleanFilter(name=f.name, lookup_type='isnull')
if lookup_type == 'in' and type(f) == filters.NumberFilter:
return filters.InSetNumberFilter(name=f.name, lookup_type='in')
if lookup_type == 'in' and type(f) == filters.CharFilter:
return filters.InSetCharFilter(name=f.name, lookup_type='in')
return f
Though if the field is provided with a choices
attribute, it won't work. see https://github.com/alex/django-filter/blob/69767e12d0265fc4d0286db80aec88acd8783cf9/django_filters/filterset.py#L444 where it gets set to ChoiceFilter instead.
if f.choices:
default['choices'] = f.choices
return ChoiceFilter(**default)
Right now the work around we are using is
class SomeFilter(filters.FilterSet):
a_field = filters.AllLookupsFilter()
a_field_in = filters.InSetCharFilter(name='a_field', lookup_type='in')
I have tried to play around a bit to find a fix but I could not come up with something sane in a timely matter. Maybe some one with more knowledge can weigh in and help out.
BooleanFilter
- no longer necessary with equivalent in rest_framework.filters
.This makes the most sense applied to django-rest-framework-filter.
Creating custom lookup filters can be tedious with DRF (not using django-rest-framework-filter):
class SessionFilter(django_filters.FilterSet):
client_type__contains = django_filters.CharFilter(name='client_type', lookup_type='contains')
client_system__contains = django_filters.CharFilter(name='client_system', lookup_type='contains')
starttime__gte = django_filters.DateTimeFilter(name='starttime', lookup_type='gte')
starttime__lte = django_filters.DateTimeFilter(name='starttime', lookup_type='lte')
starttime__range = django_filters.DateRangeFilter(name='starttime')
class Meta:
model = Session
fields = ['client_type',
'client_system',
'starttime',
'project',
'language',
]
class SessionList(generics.ListAPIView):
queryset = Session.objects.all()
serializer_class = SessionSerializer
filter_class = SessionFilter
Here's the same thing with TastyPie:
class SessionResource(ModelResource):
class Meta:
queryset = Session.objects.all()
resource_name = "session"
allowed_methods = ['get']
serializer = JSONSerializer()
filtering = {
"client_type": ('exact', 'contains',),
"client_system": ('exact', 'contains'),
"starttime": ('exact', 'gte', 'lte', 'range'),
"project": ('exact'),
"language": ('exact'),
}
It would be great if a filtering dictionary were similarly optionally supported with DRF. Maybe this should be an issue on DRF? I'm not sure.
Thanks!
The warning message is incorrect. Please refer to #72 instead.
The following issues should be merged once carltongibson/django-filter#363 is merged/released.
The above PR fixes longstanding issues with filter generation for various lookup types ('isnull', 'in', 'range'), as well as the newly introduced lookup transforms.
TODO:
fix_field_filter
, as it should no longer be necessaryInSetNumberFilter
/InSetCharFilter
At the moment the initialization of ChainedFilterSet iterates over all possible combinations of fllters. Can this be changed to instead only iterate over filters that are passed as arguments?
class ChainedFilterSet(django_filters.FilterSet):
def __init__(self, *args, **kwargs):
.....
for name, filter_ in six.iteritems(self.filters):
Hello,
After upgrading the library from 0.3.1 to 0.6.0 isnull lookup got broken.
Models:
class AcceptanceCriteria(models.Model):
name = models.CharField(max_length=40, primary_key=True)
tests = models.ManyToManyField(Test)
class Test(models.Model):
name = models.CharField(max_length=40)
Filterset:
class TestFilter(filters.FilterSet):
name = filters.AllLookupsFilter(name='name')
acceptancecriteria = filters.AllLookupsFilter(name="acceptancecriteria__name", distinct=True)
class Meta:
model = Test
Thrown exception is: Unsupported lookup 'isnull' for CharField or join on the field not permitted.
There were some other issues with previous version of library that were presumably solved in 0.6, so I've updated it and came across that problem. Could you help?
Regards,
Piotr
Because it does not implement the render
method. I also reported the issue to django-filters: carltongibson/django-filter#383
I see that the BooleanWidget was introduced to fix issue #25 by commit d3fd92b but I'm unable to reproduce issue #25 when using django.forms.BooleanField with its the default widget CheckboxInput (ie. querying ?is_active=True
, ?is_active=false
, etc. works just fine, on the contrary it's using 0
or 1
that doesn't work as it evaluates to bool("0")
or bool("1")
which is always true. So we cool just get rid of the BooleanWidget
if we're ok with just using True of False string in queries.
A better solution would be to have a BooleanWidget
inheriting from both django.forms.widget.CheckboxInput
for the render
method and rest_framework.fields.BooleanField
for the value_from_datadict
method logic:
from rest_framework.fields import BooleanField
from django.forms.widget import CheckboxInput
class BooleanWidget(BooleanField, CheckboxInput):
def value_from_datadict(self, data, files, name):
if name not in data:
# A missing value means False because HTML form submission does not
# send results for unselected checkboxes.
return False
value = data.get(name)
return self.to_internal_value(value)
And this widget coundn't be in django-filters as it doesn't depend on the rest framework but here in django-rest-framework-filters.
I'm using:
Django==1.8.9
django-filter==0.12.0
djangorestframework==3.3.2
djangorestframework-filters==0.7.0
The current __in
filter supports only filtering on integers. There are several cases where I'd like to use an __in
filter on strings. For example, when looking up several users through the username
field.
The docs imply that ALL_LOOKUPS dictionary style declarations are equivalent to use of filters.AllLookupsFilter:
...we sometimes want to allow any possible lookups on particular fields. We do this by using AllLookupsFilter:
<snip>
Additionally, you may use ALL_LOOKUPS with dictionary style declarations.
However, these two approaches are not equivalent because the dictionary approach with ALL_LOOKUPS does not call FilterSet.fix_filter_field method to make filter field / lookup adjustments. That method is only called when the filter is as actually an instance of filters.AllLookupsFilter.
class FilterSetMetaclass(filterset.FilterSetMetaclass):
def __new__(cls, name, bases, attrs):
new_class = super(FilterSetMetaclass, cls).__new__(cls, name, bases, attrs)
# Populate our FilterSet fields with all the possible
# filters for the AllLookupsFilter field.
for name, filter_ in six.iteritems(new_class.base_filters.copy()):
if isinstance(filter_, filters.AllLookupsFilter):
model = new_class._meta.model
field = filterset.get_model_field(model, filter_.name)
for lookup_type in django_filters.filters.LOOKUP_TYPES:
if isinstance(field, ForeignObjectRel):
f = new_class.filter_for_reverse_field(field, filter_.name)
else:
f = new_class.filter_for_field(field, filter_.name)
f.lookup_type = lookup_type
f = new_class.fix_filter_field(f)
request.QUERY_PARAMS
has been deprecated per: http://www.django-rest-framework.org/topics/3.1-announcement/#deprecations
Usage:
Hello.
Just tried to upgrade to Django REST framework 3.2, which was released a couple of minutes ago, and this package is the first one that broke. The problem is in the usage of the deprecated request.QUERY_PARAMS
instead of the new request.query_params
. I can write some compat code, but need to know what versions of DRF are officially supported by this package. Most importantly if you plan to support below 3.0.
Maybe adding a tox run with the supported versions would also be good to get a firmer build matrix in place.
I am using @carljm's django_model_util Choices field. is this package compatible? i ask because i am trying to create a filter that uses the human-readable version of the choices field backing a model field, and can't get it to work. if it is compatible, i'd love a concrete example to follow. thanks...
How complex can our filters be?
Say I have a Post model:
class Post:
user = models.ForeignKey(User, related_name='posts')
title = models.CharField(max_length=200)
I want to find users who have an old post about gmail AND a new post about ymail
uo = User.objects
uo= uo.filter(posts__title__icontains="gmail", posts__publish_date__lte="01/01/2009")
uo= uo.filter(posts__title__icontains="ymail", posts__publish_date__gte="01/01/2015")
I don't see how I could currently do this with DRFF? I'd actually like to be able to do much more complex filters too
The exact search i.e ?title=django
would give the right result. But whenever I use title__icontains
or title__startswith
it would return the whole ListView as in it's like without any filter. Is anyone experiencing this issue? Using Django 1.9 and DRF 3.3.2.
After upgrading past 0.4.0, I get an error when filtering on a queryset...
got an unexpected keyword arguments cache
Is there some configuration I am missing? I am using a generic view set and on django rest 3.3.2.
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/filters.py#L85
Wondering why django-rest-framework-filters
does not support using multiple values for the same field like color=green&color=blue
. In that case, I'm only getting blue
results instead of blue
+ green
.
This functionality is supported in django_filters
...
Is it possible to make my filters support this?
Cannot resolve unknown expression type, unknown output field
Any thoughts on what I am missing in my app? I see a utils.py file was added, but having trouble tracing down the problem.
I'm on the latest Django & django filter, and rest framework packages. Any thoughts on what I am missing b/w the jump from 0.7 to 0.8?
class PersonFilter(FilterSet):
full_name = AllLookupsFilter(name='full_name')
class Meta:
model = Person
class PersonViewSet(viewsets.ModelViewSet):
resource_name = 'people'
model = Person
queryset = Person.objects.all()
filter_class = PersonFilter
permission_classes = (permissions.IsAuthenticated,)
serializer_class = ps.PersonListSerializer
filter_backends = (backends.DjangoFilterBackend, filters.SearchFilter,)
search_fields = ('username', 'first_name', 'last_name', 'title', 'status__name')
Aparently the django.db.models.related
module was moved/removed/merged on latest django versions, which causes a import error when trying to use the filter backend.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.