Giter Site home page Giter Site logo

Comments (13)

jsmedmar avatar jsmedmar commented on May 20, 2024 1

@rpkilby hey! thank you very much, so I saw that django-filters merged your pull request. Thats great. I think I'll create a new "issue" for the field aliasing, I think that would be a nice feature for django-rest-framework-filters

from django-rest-framework-filters.

rpkilby avatar rpkilby commented on May 20, 2024

Hi @ericntd. There is both a list syntax and dict syntax for Meta.fields. The list syntax only creates filters for the exact lookup. You should be using the dict syntax instead.

Also, make sure to use the rest_framework_filters.backends.DjangoFilterBackend backend instead of the default backend.

from django-rest-framework-filters.

jsmedmar avatar jsmedmar commented on May 20, 2024

does the icontains filter works for a related (ForeingKey) relationship? Wondering why it isnt working for me...

from django-rest-framework-filters.

rpkilby avatar rpkilby commented on May 20, 2024

icontains does not work on a foreign key value, although it will work across relationships on a foreign field.

icontains isn't a registered lookup for FKs:
https://github.com/django/django/blob/master/django/db/models/fields/related_lookups.py

from django-rest-framework-filters.

jsmedmar avatar jsmedmar commented on May 20, 2024

I didn't get this part though:

although it will work across relationships on a foreign field

You are saying that it will work if I'm querying the primary key of the foreign object?

from django-rest-framework-filters.

rpkilby avatar rpkilby commented on May 20, 2024

For example:

class AuthorFilter(FilterSet):
    class Meta:
        model = Author
        fields = {'username': ['icontains']}

class BookFilter(FilterSet):
    author = RelatedFilter(AuthorFilter)

   class Meta:
        model = Book

You could do /books?author__username__icontains=bob. You can traverse the author FK and do an icontains on a related field.

from django-rest-framework-filters.

jsmedmar avatar jsmedmar commented on May 20, 2024

Is there a way to do a symlink to a field of a RelatedFilter? something like:

class AuthorFilter(FilterSet):
    class Meta:
        model = Author
        fields = {'username': ['icontains']}

class BookFilter(FilterSet):
    username = RelatedFilter(AuthorFilter, name="username")

   class Meta:
        model = Book

I just don't want the client to know that they are actually querying a related model, that is not relevant to them.

from django-rest-framework-filters.

rpkilby avatar rpkilby commented on May 20, 2024

I'm not sure if it will work, but you might be able to do...

class BookFilter(FilterSet):
    author = RelatedFilter(AuthorFilter, name="author__username")

from django-rest-framework-filters.

jsmedmar avatar jsmedmar commented on May 20, 2024

Ok, it didn't work... and I just realized that this solution does not work... You cannot traverse the author FK and do an icontains on a related field.

from django-rest-framework-filters.

rpkilby avatar rpkilby commented on May 20, 2024

You should be able to filter on related model fields. See this as an example - it's the same idea.

The name aliasing - not so sure about that. I'll try to look into it further.

from django-rest-framework-filters.

jsmedmar avatar jsmedmar commented on May 20, 2024

I just get empty querysets if I don't put the exact value, for example:

>> len(list(NoteFilter({"author__username__icontains": "u"}, queryset=Note.objects.all())))
0

>>len(list(NoteFilter({"author__username__icontains": "user1"}, queryset=Note.objects.all())))
2

This is my exact setting:

settings.py

REST_FRAMEWORK = {

    'PAGE_SIZE': 10,

    'DEFAULT_PAGINATION_CLASS':
        'rest_framework.pagination.LimitOffsetPagination',

    'DEFAULT_FILTER_BACKENDS': (
        'rest_framework_filters.backends.DjangoFilterBackend',
        'rest_framework.filters.SearchFilter',
         ),

    }

filters.py

class ExtractionFilter(FilterSet):

    """Extraction Filter Class."""

    #: ``analyte`` filter field.
    analyte = AllLookupsFilter(name="analyte")

    #: ``ext_id`` filter field.
    ext_id = AllLookupsFilter(name="ext_id")

    class Meta:
        model = Extraction


class WorkflowFilter(FilterSet):

    """Workflow Filter Class."""

    #: Nested filter for ``extraction`` ForeignKey relation.
    extraction = RelatedFilter(ExtractionFilter, name="extraction")

    class Meta:
        model = Workflow
>> len(list(WorkflowFilter({"extraction__analyte__icontains": "R"}, queryset=Workflow.objects.all())))
0

>> len(list(WorkflowFilter({"extraction__analyte__icontains": "RNA"}, queryset=Workflow.objects.all())))
100

from django-rest-framework-filters.

jsmedmar avatar jsmedmar commented on May 20, 2024

Ok I think I found the problem...

icontains does not work with fields that have choices (analyte) but it does work on fields without choices (ext_id):

class Extraction(Model):

    analyte = models.CharField(
        verbose_name=_("Biological Material"),
        max_length=100,
        choices=CHOICES,
        null=True,
        )

    ext_id = models.CharField(
        verbose_name=_("Extraction External ID"),
        max_length=100,
        blank=True,
        default=None,
        )

Is this an expected behavior?

from django-rest-framework-filters.

rpkilby avatar rpkilby commented on May 20, 2024

does not work with fields that have choices

Great catch! This if statement has been nagging me for a very long time but decided to just leave it be. The problem is that the value being filtered won't match any of the choices, so it won't validate and returns 0 results. I've submitted a PR (carltongibson/django-filter#447) to only create choice filters for exact lookups (which was probably the original intent anyway).

The following should get around this:

class FilterSet(filters.FilterSet):

    @classmethod
    def filter_for_lookup(cls, f, lookup_type):
        # copy field and remove choices to bypass default behavior
        # See: https://github.com/carltongibson/django-filter/issues/447
        if f.choices and lookup_type != 'exact':
            f = deepcopy(f)
            f.choices = None

        return super(FilterSet, cls).filter_for_lookup(f, lookup_type)

from django-rest-framework-filters.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.