miki725 / django-url-filter Goto Github PK
View Code? Open in Web Editor NEWDjango URL Filter provides a safe way to filter data via human-friendly URLs.
Home Page: http://django-url-filter.readthedocs.io/
License: Other
Django URL Filter provides a safe way to filter data via human-friendly URLs.
Home Page: http://django-url-filter.readthedocs.io/
License: Other
I'm using python 3.6 and after installing django-url-filter my test runner is broken. Turns out that it's caused by the enum34 package which is not compatible with the standard library enum, which is used by other standard library modules such as re
.
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "<string>", line 3, in <module>
File "/usr/local/lib/python3.6/site-packages/execnet/gateway_base.py", line 18, in <module>
import traceback
File "/usr/local/lib/python3.6/traceback.py", line 5, in <module>
import linecache
File "/usr/local/lib/python3.6/linecache.py", line 11, in <module>
import tokenize
File "/usr/local/lib/python3.6/tokenize.py", line 33, in <module>
import re
File "/usr/local/lib/python3.6/re.py", line 142, in <module>
class RegexFlag(enum.IntFlag):
AttributeError: module 'enum' has no attribute 'IntFlag'
It seems that there is a package that solves this. It will install enum34 only on versions < 3.4, to avoid messing with the standard library enum in current versions of python 3.
I'm trying to filter on a jsonfield in django named data_filters
. However it seems like this is not working when I'm not specifying any filters. And when i try to spesify filters it crashes because the same fields are not present everywhere.
Is there a way to not validate filters? So that i can just pass along any filter value? for example ?data_filters__region__id=01,02
Edit: Can i use the plain filter to acchieve this?
Also it seems like the pip install version of this gem (0.2.0) does not include the plain version of the filter, it seems like i have to request the master branch to get this.
Hi Team,
using below
Django 2.0
DRF 3.7
Below is my filterClass and I made changes to strict_mode still I do not get validation error.
I entered the below url on browser
http://127.0.0.1:8000/api/listmydata/?nonexistcolumn=123
I was expecting a validation error, but I get the result set which is the default behavior of strict_mode. How do I override to fail?
Am I making a mistake here in over riding in my filter Class?
from url_filter.filtersets import ModelFilterSet, StrictMode
class myCustomFilterSet(ModelFilterSet):
strict_mode = StrictMode.fail
#strict_mode = 'fail' #I tried this as well
class Meta(object):
model = myModel
class MyDataList(generics.ListAPIView):
queryset = MyModel.objects.all()
serializer_class = mySerializer
filter_class = myCustomFilterSet
Thanks
Having form validate all of the query data, might as well add ordering support.
I have a case where I have a list of dictionaries containing my data and I want to be able to filter this via a URL query. There are no models involved here because the data is processed and manipulated in memory so I cannot specify anything for the queryset parameter unless this can be set to a list of objects.
I need something like this from your example here
fs = UserFilterSet(data=query, quertset=[
{'id': 1, 'name':'hello'},
{'id': 2, 'name':'world'},
])
Is this possible with django-url-filter?
I don't know if this is an issue or a feature :) But when the filter value does not exist all the results are returned, for example:
/?state=done
# (Returns only the results where the field state is equal to 'done')
/?state=xpto
# (Returns all the results instead of none) (I think this is **not** the expected behaviour)
Note:
This behaviour does not apply if the field is int, for example id=33 (If 33 does not exist it returns empty).
I imagine most native Django integration will attempt to use a form for the filtering on the list pages. Therefore it probably makes sense to provide a way to create a form dynamically with the form fields from the filterset filters from their default lookups. For example:
class MyFilterSet(FilterSet):
foo = Filter(form_field=forms.CharField(max_length=50))
bar = Filter(form_field=forms.IntegerFIeld(max_value=100), default_lookup='in')
# generated form will be something like:
class MyFilterForm(forms.Form):
foo = forms.CharField(max_length=50)
bar = MultipleValuesField(child=forms.IntegerFIeld(max_value=100))
using that form you can easily add filtering to the template either via vanilla django forms rendering or customize layout via crispy forms.
The challenge here is how do you enable the url-filter functionality within that form? If the above form would be auto generated its all very nice but not very useful. The whole point of this lib was to allow to filter with multiple lookups on the same field dynamically. How do you do that in django form though? Adding a form field for each lookup is ugly and user will see too many form fields so filter form experience would be terrible:
class MyFilterForm(forms.Form):
foo = forms.CharField(max_length=50)
foo__exact = forms.CharField(max_length=50)
foo__contains = forms.CharField(max_length=50)
...
The best I came up with so far is to be able to specify for which lookups to create the form with. A form will be limited to a single lookup for each field but at least which lookup is used will be customizable.
Maybe something like this will work:
class MyFilterForm(FilterForm):
class Meta(object):
filterset = MyFilterSet
lookups = { # if not provided will use default lookups from each filter
'bar': 'range',
}
I couldn't find an indication on Github, ReadtheDocs or in the code that suggests that there is support for this.
Basically, in the Meta class of a serializer, you can specify fields = 'all' to indicate that the serializer should represent all fields in its return.
Similarly, I'm keen to see if we can currently use something like filter_fields = '__all__'
in the view/viewset definition.
The behaviour will then essentially automatically allow filtering on all model fields for that viewset.
Thoughts?
I know that queries like datetimefield__gte=2019-01-05 is supported.
How do I get even more granular and use timestamps here (eg. 2019-01-05T18:21:57.534972-08:00) ?
With current library, it is possible to have negative lookups, like this:
title__contains!=WIP
will yield all the entries not containing "WIP", which works well.
Now, let's suppose we want to have all entries not containing WIP which are authored by 'admin'. No problem, we just add another clause here: title__contains!=WIP&author=admin
.
But what if we also want filter this set down by adding a condition of entry not having 'draft' status? Logic tells us to add another negative condition: title__contains!=WIP&author=admin&status!=draft
.
Unfortunately, with current implementation, it'll result to the following SQL: select * from entry_entries where author = 'admin' and not (title like '%WIP%' and status='draft')
which seems a bit illogical. Correct (IMO) behavior would translate this filter URL to select * from entry_entries where author = 'admin' and not title like '%WIP%' and not status = 'draft'
.
The reason is that implementation of filtering tries to deal with multiple positive and negative filters similarly:
include = {self._prepare_spec(i): i.value for i in self.includes}
exclude = {self._prepare_spec(i): i.value for i in self.excludes}
if include:
queryset = queryset.filter(**include)
if exclude:
queryset = queryset.exclude(**exclude)
However, .exclude() logic with multiple kwargs differs from .filter(). Django doc suggests to use chained .exclude() instead to achieve similarity to .filter()
That's why I suggest to fix this logical issue by changing implementation.
Hello!
# Need:
some_method(SomeModel.objects.filter(some_field='some_value'))
# returns '?some_field__exact=some_value'
Is there such a function?
django-url-filter uses some features that have been deprecated with django version 2.0
Usage of field.rel has been deprecated. Use field.remote_field instead.
This is used at least one place in django-url-filter.
https://github.com/miki725/django-url-filter/blob/master/url_filter/filtersets/django.py#L126
Currently only 1.8 is supported. We should support at least 1.7 and maybe even 1.4 since its still LTS and I imagine many people are still using it.
Is this how parsing and validation of ranges happen for django-url-filter?
GET /model/?departure__range=2017-01-01,2017-01-30
Based on the documentation, it seems I should just be able to configure my viewset as follows and automatically get filtering. However, certain URL filtering seems to be ignored completed.
from django_filters.rest_framework import DjangoFilterBackend
class UsersViewSet(ModelViewSet):
queryset = MyModel.objects.all()
serializer_class = MyModelSerializer
filter_backends = [DjangoFilterBackend]
filter_fields = ['id']
Assuming that viewset maps to an endpoint like /users/
, I should be able to use a query like /users?id__in=1,2,3,4,5
and only see results where the ID is either 1, 2, 3, 4 or 5.
However, that's not the case. Using that minimal setup, I can only use a filter like /users/?id=1
. As soon as I use id__in=1,2,3,4,5
, I get my entire queryset back - all 20 users.
Am I missing a setup step?
I really like what you're doing here & will probably be rolling this into a production app but I'm curious to know what your support situation is for this project. Do you currently use it in any production apps? Do you still consider yourself as actively maintaining this project? Do you follow along with latest deprecations of django & DRF & update this project & do you plan on continuing to do so?
I'm not asking because I expect you to do any of the above lol (you've already built something really nice & are generous enough to release it) but just curious where you stand. Thanks & feel free to close immediately.
When filtering on many-to-one models on the foreign key model, it causes a join which then returns non-distinct results. Found as part of looking at #18.
Can you help me to create a backend for ElasticSearch?
https://elasticsearch-dsl.readthedocs.io/en/6.2.1/
I don't want to use django models
Hi, I can use the url-filter manually for related models multiple levels deep like this:
from django.http import QueryDict
from url_filter.filtersets import ModelFilterSet
class FilterSet(ModelFilterSet):
class Meta(object):
model = TransferRequest
>>> q = QueryDict('transfer_job__transfer_session__priority=1')
>>> fs = FilterSet(data=q, queryset=TransferRequest.objects.all())
>>> fs.filter()
<QuerySet [<TransferRequest: ffdf29cb-1de7-4553-9c8b-b476a0d9d9f0>, ...
but if I have a model view set like this:
class TransferRequestViewSet(QueryOrderableViewSetMixin, viewsets.ModelViewSet):
queryset = TransferRequest.objects.all()
serializer_class = TransferRequestSerializer
filter_backends = [DjangoFilterBackend]
filter_fields = ['source_studio', 'destination_studio', 'requester_studio', 'user', 'created',
'priority', 'options', 'status', 'paths', 'guid',
# relation names
"transfer_job", "transfer_job__transfer_session"]
and I enter a URL like this:
http://localhost/api/requests/?transfer_job__transfer_session__priority=1
I get the following error:
2018-06-07T00:16:21.404012283Z KeyError: 'transfer_job__transfer_session'
2018-06-07T00:16:21.404015892Z
2018-06-07T00:16:21.404019373Z During handling of the above exception, another exception occurred:
2018-06-07T00:16:21.404022912Z
2018-06-07T00:16:21.404026226Z Traceback (most recent call last):
2018-06-07T00:16:21.404029726Z File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
2018-06-07T00:16:21.404033418Z response = get_response(request)
2018-06-07T00:16:21.404048822Z File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
2018-06-07T00:16:21.404052804Z response = self.process_exception_by_middleware(e, request)
2018-06-07T00:16:21.404055994Z File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
2018-06-07T00:16:21.404059390Z response = wrapped_callback(request, *callback_args, **callback_kwargs)
2018-06-07T00:16:21.404062545Z File "/usr/local/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
2018-06-07T00:16:21.404065945Z return view_func(*args, **kwargs)
2018-06-07T00:16:21.404068985Z File "/usr/local/lib/python3.6/site-packages/rest_framework/viewsets.py", line 103, in view
2018-06-07T00:16:21.404072336Z return self.dispatch(request, *args, **kwargs)
2018-06-07T00:16:21.404075373Z File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py", line 483, in dispatch
2018-06-07T00:16:21.404078630Z response = self.handle_exception(exc)
2018-06-07T00:16:21.404081677Z File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py", line 443, in handle_exception
2018-06-07T00:16:21.404085025Z self.raise_uncaught_exception(exc)
2018-06-07T00:16:21.404088460Z File "/usr/local/lib/python3.6/site-packages/rest_framework/views.py", line 480, in dispatch
2018-06-07T00:16:21.404091759Z response = handler(request, *args, **kwargs)
2018-06-07T00:16:21.404094827Z File "/usr/local/lib/python3.6/site-packages/rest_framework/mixins.py", line 40, in list
2018-06-07T00:16:21.404098214Z queryset = self.filter_queryset(self.get_queryset())
2018-06-07T00:16:21.404101283Z File "/usr/local/lib/python3.6/site-packages/rest_framework/generics.py", line 152, in filter_queryset
2018-06-07T00:16:21.404104530Z queryset = backend().filter_queryset(self.request, queryset, self)
2018-06-07T00:16:21.404108429Z File "/usr/local/lib/python3.6/site-packages/url_filter/integrations/drf.py", line 160, in filter_queryset
2018-06-07T00:16:21.404111880Z return _filter.filter()
2018-06-07T00:16:21.404115061Z File "/usr/local/lib/python3.6/site-packages/url_filter/filtersets/base.py", line 324, in filter
2018-06-07T00:16:21.404118401Z specs = self.get_specs()
2018-06-07T00:16:21.404121429Z File "/usr/local/lib/python3.6/site-packages/url_filter/filtersets/base.py", line 358, in get_specs
2018-06-07T00:16:21.404124811Z specs.append(self.get_spec(data))
2018-06-07T00:16:21.404127821Z File "/usr/local/lib/python3.6/site-packages/url_filter/filtersets/base.py", line 400, in get_spec
2018-06-07T00:16:21.404131037Z if name not in self.filters:
2018-06-07T00:16:21.404134085Z File "/usr/local/lib/python3.6/site-packages/cached_property.py", line 35, in __get__
2018-06-07T00:16:21.404138102Z value = obj.__dict__[self.func.__name__] = self.func(obj)
2018-06-07T00:16:21.404141194Z File "/usr/local/lib/python3.6/site-packages/url_filter/filtersets/base.py", line 224, in filters
2018-06-07T00:16:21.404147396Z filters = self.get_filters()
2018-06-07T00:16:21.404150516Z File "/usr/local/lib/python3.6/site-packages/url_filter/filtersets/base.py", line 487, in get_filters
2018-06-07T00:16:21.404153786Z _filter = self._build_filter(name, state)
2018-06-07T00:16:21.404156840Z File "/usr/local/lib/python3.6/site-packages/url_filter/filtersets/django.py", line 93, in _build_filter
2018-06-07T00:16:21.404160186Z field = self.Meta.model._meta.get_field(name)
2018-06-07T00:16:21.404163206Z File "/usr/local/lib/python3.6/site-packages/django/db/models/options.py", line 619, in get_field
2018-06-07T00:16:21.404166434Z raise FieldDoesNotExist("%s has no field named '%s'" % (self.object_name, field_name))
2018-06-07T00:16:21.404169750Z django.core.exceptions.FieldDoesNotExist: TransferRequest has no field named 'transfer_job__transfer_session'
Is there a special syntax for entering such filters ?
Thanks
-Selim
Having the imports in the examples would be really useful, especially since you have two different DjangoFilterBackend
classes (thankfully they take different numbers of __init__
arguments, otherwise I would have been extremely confused).
pip install django-url-filter only the files in the root without the sub-directories.
This package seems great and I would like to try work with it! :-)
-thanks, Eli.
I'm using this to filter ListViews beautifully now. Thanks. Love it.
I find myself wanting at the top of the list view to summarise the filter in use. Alas no quick easy way to format it seems available.
self.request.GET of course contains the GET parameters. and FilsterSet.get_specs() also provides a parsed view I guess of those GET parameters that made it into the filter. But I see now easy way to print either as a nice HTML list of the filter criteria.
I may write one yet, but first a check to see if there is a way I'm missing, and second a check to see if I write one if it would be a welcome pull request into this package?
Hi I have a callable filter that handles a custom lookup that I implemented:
class StatusFilter(CallableFilter):
@form_field_for_filter(forms.CharField())
def filter_has_any_keys_for_django(self, queryset, spec):
value = spec.value.split(',')
if spec.is_negated:
return queryset.exclude(status__has_any_keys=value)
else:
return queryset.filter(status__has_any_keys=value)
@form_field_for_filter(forms.CharField())
def filter_contains_for_django(self, queryset, spec):
if spec.is_negated:
return queryset.exclude(status__contains=spec.value)
else:
return queryset.filter(status__contains=spec.value)
And it works great. The issue is that if the callable filter doesn't support other types of lookups, I want it to fall back to the default way of handling the filters, so for example if I try to specify a query parameter like ".../?status=["complete","succeeded"] then I get an error:
AssertionError: StatusFilter was not provided form_field parameter in initialization (e.g. StatusFilter(form_field=CharField)) and form_field was not provided for the lookup. If the lookup is a custom filter callable you should provide form_field by using @form_field_for_filter decorator. If the lookup is a normal lookup, then please either provide form_field parameter or overwrite get_form_field().
Is there a mechanism for this?
Thanks
-Selim
I am working on DRF generic listview with DUF as filter backend.
Could you please assist me to get around this error? I am sure i am doing something wrong here with related to related fields.
When i try to filter on url I get the following error. I would like to filter on all columns of child model.
http://127.0.0.1:8000/api/childlist/?customer_id=2
AttributeError at /api/childlist/
'OneToOneField' object has no attribute 'rel'
Below is my work so far:
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Parent(models.Model):
customer_id = models.BigIntegerField(primary_key=True)
customer_name = models.CharField(blank=True, null=True, max_length=50)
age = models.IntegerField(blank=True, null=True)
class Child(models.Model):
customer_id = models.OneToOneField(Parent, on_delete=models.DO_NOTHING, related_name='customer_id_fk_parent')
used_by = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name='rel_user')
comments = models.TextField(blank=True,null=True)
views.py
from rest_framework import generics
from onetoone.models import Child
from .serializers import Child_Serializer
from url_filter.integrations.drf import DjangoFilterBackend
#Required columns on Child -- All columns
FILTER_REQ_COLUMNS = [field.name for field in Child._meta.get_fields()]
class ChildList(generics.ListAPIView):
queryset = Child.objects.all()
serializer_class = Child_Serializer
filter_backends = [DjangoFilterBackend]
filter_fields = FILTER_REQ_COLUMNS
serializers.py
from rest_framework import serializers
from onetoone.models import Child
class Child_Serializer(serializers.ModelSerializer):
class Meta:
model = Child
exclude = []
urls.py
path('childlist/', ChildList.as_view(), name='api_child_list'),
Current list data as below
http://127.0.0.1:8000/api/childlist/
HTTP 200 OK
Allow: GET, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"count": 3,
"next": null,
"previous": null,
"results": [
{
"id": 1,
"comments": "1 is in use",
"customer_id": 1,
"used_by": 1
},
{
"id": 2,
"comments": "2 is in use",
"customer_id": 2,
"used_by": 1
},
{
"id": 3,
"comments": "3 in use",
"customer_id": 3,
"used_by": 1
}
]
}
fulltrace back is here
https://gist.github.com/just10minutes/b9add9c00ee3a14764b324ec30c65344
I have plenty of SQLAlchemy code bases that are not based on Django where this library could be useful.
It looks like the sqlalchemy backend itself can be used without Django as I don't see any references to Django imports:
http://django-url-filter.readthedocs.io/en/latest/_modules/url_filter/backends/sqlalchemy.html
Have you considered splitting this part out to a separate library? For now I would have to copy this file in my codebase (keeping the comments + copyright reference off course), but it would be nice not to have to do this in the future.
The requirements.txt pulls in Django as a dependency that is why I can't exactly use it, it would basically trigger it installing Django in a flask project, or bottle project etc.
Taking these models:
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
class Restaurant(models.Model):
place = models.OneToOneField(Place, primary_key=True)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
RestaurantFilterSet
should then include both children place
filterset and place_id
.
Doing that will allow to optimize filtering by not causing unnecessary joins for urls like:
place_id=5
vs
place__id=5 == place=5
Django URL filter should be able to filter on plain Python lists
It seems that most query filtering tools for django have poor support for paging/pagination.
Either inbuilt support, Django's built in pagination capabilities or via other existing pagination libraries/apps.
Does django-url-filter support pagination in any way?
If not, can we build it in or support the 'default' django mechanisms?
Being able to just add paginate_by = 10
on my class based views, is pretty damn useful when trying to be productive.
Hi,
for a project that use drf-yasg, i use CallableFilter for model properties that returns queryset.
But when doc was generated with drf-yasg, many lookups were generated when I didn't create them.
For now, I override the lookups method like this:
@cached_property
def lookups(self):
r = LOOKUP_CALLABLE_FROM_METHOD_REGEX
custom_lookups = {
m.groupdict()["filter"]
for m in (r.match(i) for i in dir(self))
if m and m.groupdict()["backend"] == self.root.filter_backend.name
}
return custom_lookups
Would there be a possibility to choose that this method only returns the custom lookups?
A parameter custom_lookups_only=False
in the __init__
of CallableFilter
for example?
__repr__
should have better representation for easier debugging. should be similar to how DRF does this
Is it possible to get an example of how to use this library with a Class Based View?
Either the built in Django ListView or the Django Vanilla Views ListView, would be enough to show how this can be used without DRF a bit easier than the current example of manually creating things does.
It seems that if the decimal in the url is not within the specifications given in the model definition, then the filter fails and returns everything.
class Test(models.Model):
my_number = models.DecimalField(max_digits=2, decimal_places=1)
Test.objects.create(my_number=1.5)
1 result:
/test/
/test/?my_number__gte=1
/test/?my_number__gte=1.0
/test/?my_number__gte=.0
/test/?my_number__gte=2.00 <- incorrect
/test/?my_number__gte=20 <- incorrect
0 results:
/test/?my_number__gte=2
/test/?my_number__gte=2.0
This should work:
class MyFilterSet(ModelFilterSet):
class Meta:
model = Foo
fields = ['foo'] # not a model field
extra_kwargs = {'foo': {'source': 'bar'}} # bar is a field on model
ModelFilterSet
should support to specify lookups in Meta
:
class Meta:
model = Foo
lookups = {
"slug": ('exact', 'startswith',),
"title": ALL,
}
that should fix:
Traceback (most recent call last):
File "/home/serkan/.local/share/virtualenvs/slides-2sl0-4FG/src/sliderepl/sliderepl/core.py", line 292, in run
exec_(co, environ)
File "<input>", line 1, in <module>
File "/home/serkan/.local/share/virtualenvs/slides-2sl0-4FG/lib/python3.6/site-packages/url_filter/filtersets/__init__.py", line 5, in <module>
from .django import * # noqa
File "/home/serkan/.local/share/virtualenvs/slides-2sl0-4FG/lib/python3.6/site-packages/url_filter/filtersets/django.py", line 6, in <module>
from django.contrib.contenttypes.fields import GenericForeignKey
File "/home/serkan/.local/share/virtualenvs/slides-2sl0-4FG/lib/python3.6/site-packages/django/contrib/contenttypes/fields.py", line 5, in <module>
from django.contrib.contenttypes.models import ContentType
File "/home/serkan/.local/share/virtualenvs/slides-2sl0-4FG/lib/python3.6/site-packages/django/contrib/contenttypes/models.py", line 139, in <module>
class ContentType(models.Model):
File "/home/serkan/.local/share/virtualenvs/slides-2sl0-4FG/lib/python3.6/site-packages/django/db/models/base.py", line 118, in __new__
"INSTALLED_APPS." % (module, name)
RuntimeError: Model class django.contrib.contenttypes.models.ContentType doesn't declare an explicit app_label and isn't in an application in INSTALLED_APPS.
Hello,
first let me thank you for sharing this useful code!
What i found is that if you try to filter by a field that point to a related model which has defined a generic foreign key followinf error is returned:
AttributeError at /api/v1/projects/a/ 'GenericForeignKey' object has no attribute 'formfield'
I tried with ForeignKey and ManyToMany on django 1.9.7 and url_filter from github master branch.
You can test it with the following two models:
from django.db import models
from django.contrib.contenttypes.fields import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
class A(models.Model):
name = models.CharField(max_length=256, blank=False, null=False)
class B(models.Model):
name = models.CharField(max_length=256, blank=False, null=False)
a = models.ForeignKey('A',
models.DO_NOTHING,
blank=True,
null=True,
related_name='b_rel')
content_type = models.ForeignKey(ContentType, models.DO_NOTHING)
object_id = models.PositiveIntegerField()
content_object = GenericForeignKey('content_type', 'object_id')
If you try to filter the model 'A' list by the 'b_rel' field the error appears.
Since i actually tried filtering trough djangorestframework 3.3.3 (even if i think that thi issue is generic), i will leave here the relevant code to publish model 'A' to a rest API so you can test it easily.
Just create an 'A' record and paste the following url after you authenticated (trough the django rest framework browsable api or standard django admin):
http://localhost:8000/api/your-app-name/a/?b_rel=1
views.py
from .serializers import *
from projects.models import A, B
from rest_framework.viewsets import ModelViewSet
class ASerializer(serializers.ModelSerializer):
class Meta:
model = A
fields = [
'name',
'b_rel',
]
class AViewSet(ModelViewSet):
serializer_class = ASerializer
queryset = A.objects.all()
filter_backends = [DjangoFilterBackend]
filter_fields = [
'name',
'b_rel',
]
urls.py
from django.conf.urls import include, url
from rest_framework import routers
from projects.views import AViewSet
router = routers.DefaultRouter()
router.register(r'a', AViewSet, 'projects-a')
urlpatterns = [
url(r'^api/your-app-name/', include(router.urls)),
]
Since the error occurs when filters for the related model ('B') are built automatically, imho the solution is to check wheter a field actually has a formfield or at least exclude the 'GenericForeignKey' field from filters because they do not have a form field by default, see relevant django documentation..
If you prefer a pull request, just tell me.
I can't seem to find documentation on filtering fields by null value. By logic, Django's isnull=True
should work, but it doesn't work for me:
/api/houses/?ownerid__isnull=True
doesn't filter houses with no owner
I am not sure how complex to implement this, but it would be really useful if we can filter on aggregate (annotated) fields.
Exmaple:
Consider these models
from django.db import models
class Reporter(models.Model):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
email = models.EmailField()
class Article(models.Model):
headline = models.CharField(max_length=100)
pub_date = models.DateField()
reporter = models.ForeignKey(Reporter)
And the DRF viewset
from rest_framework import viewsets
class ReporterViewSet(viewsets.ReadOnlyModelViewSet):
queryset = models.Reporter.objects.annotate(article_count=Count("reporter_set"))
filter_backends = [DjangoFilterBackend]
filter_fields = ['last_name', 'article_count']
We filter reporters that have at least n articles by reporter?article_count__gte=5
.
This setup currently result in error Reporter has no field named 'article_count'
. Since the filtering is done on the queryset not the model, I am not sure why the model is being checked.
Thanks.
Hi there,
First of all many thanks for sharing this with the world. It might have saved me a lot of time :)
I'm using django-url-filter 0.2.0 DRF integration with DRF 3.3.2 and Django 1.9.2.
One of the 2 uses I'd like to give it I think is not working though. Here's how my code looks like (I'm not pasting my settings since the rest seems to be working fine):
# In models.py
class E(models.Model):
title = models.CharField(max_length=200)
p = models.ForeignKey('P')
class P(models.Model):
name = models.CharField(max_length=200)
# In views.py
class EViewSet(viewsets.ModelViewSet):
serializer_class = ESerializer
queryset = E.objects.all()
filter_fields = ['p']
class PViewSet(viewsets.ModelViewSet):
serializer_class = PSerializer
queryset = P.objects.all()
What I'd like to do is filter all E instances that belong to a certain list of Ps (ie. being able to do http://example.com/v1/e/?p__in=1,2,3
or similar).
The result I'm getting is just all the E objects, unfiltered. I'm not sure if this is supposed to be working but broken or if it's a functionally yet to be added, or maybe I'm just doing it wrong. Sorry I didn't dive in the code to pin point the exact cause of the problem.
Thanks for your help!
__date lookup for a DateTimeField doesn't work.
Currently only django 1.11 is tested in travis, because the MakeFile command doesn't run tox. Instead theres'
It's rather confusing to have a tox config and not actually use it for continuous integration. Tox is more configurable than just using varibles in the .travis.yml file.
https://github.com/miki725/django-url-filter/blob/master/Makefile
https://github.com/miki725/django-url-filter/blob/master/.travis.yml
There is a tox config file, but there's some problems when installing pip packages with pypy.
https://github.com/miki725/django-url-filter/blob/master/tox.ini
Forgive me. But on this page:
https://github.com/miki725/django-url-filter/blob/master/docs/usage.rst
There is an enticing Django section after a Vanilla section that makes no sense to me. And in it I expect to see how I might use this in Django. But that section helps me naught.
It presents some code snippets out of context and I'm a tad clueless as to to use filters from it.
Where does what sit in urls.py, models.py, views.py, settings.pi etc. in the Django context? What am I missing? How could this page improve to actually elucidate things for a punter like me (building a site with Django, pretty au fait with much of Django but unable to decrypt this so clearly not a pro).
I have a ViewSet that runs well with django-filter but in django-url-filter I have an error (at the end)
The viewSet:
from url_filter.backends.django import DjangoFilterBackend
class PersonaViewSet(viewsets.ModelViewSet):
filter_fields = ['nom', 'cognoms', 'data_naixament', 'fills', 'casat']
queryset = Persona.objects.all()
serializer_class = PersonaSerializer
filter_backends = [DjangoFilterBackend]
My packages are:
Django==1.9.8
django-filter==0.15.0
django-url-filter==0.2.0
djangorestframework==3.4.6
The error:
Environment:
Request Method: GET
Request URL: http://devel-trusty.local:8000/persones/?id=1
Django Version: 1.9.8
Python Version: 2.7.6
Installed Applications:
['django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'quickstart']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware']
Traceback:
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
response = self.process_exception_by_middleware(e, request)
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
response = wrapped_callback(request, _callback_args, *_callback_kwargs)
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/django/views/decorators/csrf.py" in wrapped_view
return view_func(_args, *_kwargs)
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/rest_framework/viewsets.py" in view
return self.dispatch(request, _args, *_kwargs)
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
response = self.handle_exception(exc)
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/rest_framework/views.py" in handle_exception
self.raise_uncaught_exception(exc)
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/rest_framework/views.py" in dispatch
response = handler(request, _args, *_kwargs)
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/rest_framework/mixins.py" in list
queryset = self.filter_queryset(self.get_queryset())
File "/devel/infraplan/layer_manager/env/local/lib/python2.7/site-packages/rest_framework/generics.py" in filter_queryset
queryset = backend().filter_queryset(self.request, queryset, self)
Exception Type: TypeError at /persones/
Exception Value: init() takes at least 2 arguments (1 given)
how could I filter a model by the smallest and highest price for example?
Hi,
How can I achieve case insensitive filter on my requests?
for eg:
http://127.0.0.1:8000/api/customers/?in_use=No -- This works
http://127.0.0.1:8000/api/customers/?in_use=no -- Does not work because database stored this value as No
I think we have to use iexact option instead of exact, but not getting where to over ride this without impacting the original library.
Your assistance is helpful here
Thanks
Hi, I have a model with a JSONField which contains an array of strings:
class TransferSession(models.Model):
...
status = JSONField(default=[], validators=[validate_session_status])
I can use filters like this in the URL which works fine:
/api/sessions/?status__contains="running"
Now I'd like to use the "has_any_keys" filter to match any of the given values:
/api/sessions/?status__has_any_keys=["running","stopped"]
but it doesn't seem to work. Is it not currently supported?
Thanks
-Selim
Is there a way possibility to do complex lookups via the url?
Suppose I have a model "Car" with a field called "fuel_tank_capacity" that can be null. How can I filter for all Cars with a fuel_tank_capacity__gte=80 but also include those cars where fuel_tank_capacity is empty?
In Django terms, what I'd like to be able to do via url filtering is
Car.objects.filter(Q(fuel_tank_capacity__gte=80) | Q(fuel_tank_capacity=None))
Thanks for the great work by the way, keep it up!
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.