3

I am trying to implement custom filtering in my code and went through the documentation. But I couldnt understand the following snippets from the docs.

class UserFilter(django_filters.FilterSet):
    class Meta:
        model = User
        fields = ['username', 'last_login']

# or

class UserFilter(django_filters.FilterSet):
    class Meta:
        model = User
        fields = {
            'username': ['exact', 'contains'],
            'last_login': ['exact', 'year__gt'],
        }

The doc says we can use either one the first or second one but what is the exact difference?? What is the meaning of contains and year_gt?

2 Answers 2

4

What is the exact difference ?

With fields = ['username', 'last_login'], the generated filters are :

qs.filter(username='some_value') and qs.filter(last_login=some_date_value)

With

fields = {
        'username': ['exact', 'contains'],
        'last_login': ['exact', 'year__gt'],
    }

the generated filters are :

qs.filter(username='some_value'), qs.filter(username__contains='some_value') for the username field.

qs.filter(last_login=some_date_value), qs.filter(last_login__year__gt=some_year_value) for the last_login field.

So we can see at first time that the second produce 2 filters options for each field, and the first produce only one filter option (exact match) for the given value.

What is the meaning of contains and year__gt ?

contains is used to filter by a value that can be found inside a field. ex: dj is in django.

year__gt in other hand is only for date field. When you have a date field like created, Django let you filter by the year, month, day by just do : .filter(created__year=2021, created__month=12). And more possibility by .filter(created__year__gt=2020) that means the year of created field > 2020. It can be applied to month__gt (month > 11), day__lt (day < 25).

Sign up to request clarification or add additional context in comments.

2 Comments

thanks for your answer, but when i call the api /api/person?username__exact i have to pass query paramter like this or only /api/person?username in second way??? thats my confusion
/api/person?username__exact and /api/person?username are the same because the exact option is the default behavior. Now for contains you need something like /api/person?username__contains=some_value.
2

There's a link in the docs there for the django lookups docs also, and what you'll find with this is that you can make searching/filtering more efficient by using that second option.

The first option in the docs, where fields is just a list will do an exact match query against each of the fields you list.

In the second option, hat the filters library will do with the fields dictionary is it'll use "double underscore" notation to create lookups of;

  • username__exact
  • username__contains
  • last_login__exact
  • last_login__year__gt

You can use the double underscore to access an attribute of something, or the lookup type. So on last_login for that final example above, it'll take the year of the last_login value and for that year, the lookup type is greater than (gt).

There are lots of these lookup values that can be really helpful to learn. For example, contains is case sensitive but you can use icontains for a case insensitive match. There's also lt for less than, or lte/gte for less/greater than or equal. Check out the available lookups here.

10 Comments

Thanks, for the beautiful explanation @markwalker. so for the second way i have to use /api/person?username__contains or /api/person?username__exact not only username like in the first case, right?
@Django-Rocks I don't think you really need to do anything besides define that fields attribute how best suits you. Those paths would be correct, but filters should take care of things so you don't have to. What I'd say is that option 2 is the best approach, it's efficient and you can control the queries more.
thanks for your answer, but when i call the api /api/person?username__exact i have to pass query paramter like this or only /api/person?username in second way??? thats my confusion
Ah I think I understand now. If you setup with option 2, then you'd query the server with /api/person?username__exact=mark for example, then mark gets fed into that FilterSet class using the fields dictionary to do an exact match on username. Does that answer that for you?
You'd likely use the in lookup there. You can use a list with that, so /api/person?username__in=mark,ben,bob,steve. You can also use these lookups when viewing the django admin if you want to see how things might work before adding them to your api.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.