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

Change lookup_type for CharField #78

Closed
duduklein opened this issue Feb 11, 2013 · 5 comments
Closed

Change lookup_type for CharField #78

duduklein opened this issue Feb 11, 2013 · 5 comments

Comments

@duduklein
Copy link
Contributor

It's very common when filtering strings to look for substrings instead of the string itself.

It would be very useful to have a way to change globally (or per FilterSet) the default lookup_type for CharFields from "exact" to "icontains".

In #75 there is a comment about a search field, so there seems to be more demand for it.

I'm willing to implement it and make a pull request, if we agree on how to implement it.

I see 2 possibilities:

  1. override the filter method in CharField like it was done for the BooleanField.
  2. make the filter method accept another parameter, which would be the lookup_type. This would default to "exact", for backward compatibility. This would allow us to change per FilterSet, which I would say it's already great.
  3. add a variable in the settings file to change the global default and make 1) use this value.

I don't really like 1), because it breaks backward compatibility. 3) would allow for not breaking compatibility by setting the default to "exact" (i.e in case no variable is set in the settings.py module"), but I prefer not to overload the settings.py module with more settings..., so I vote for 2).

If everybody agrees, i can go ahead and implement 2.

Let me know your suggestions.

@skizzay
Copy link

skizzay commented Feb 11, 2013

I think a fourth option would be to inherit from CharField and override init, defaulting the lookup_type to icontains.

@duduklein
Copy link
Contributor Author

You mean inherit from CharFilter, right? In this case, I would need another way to associate the CharFields to the new IcontanisCharFilter.

@skizzay
Copy link

skizzay commented Feb 11, 2013

That's what I meant, but after reviewing the association, I realize it would be too complicated to implement.

@nkryptic
Copy link
Contributor

@skizzay and @duduklein,

The fourth option is the one currently supported. It's quite easy to set a custom filter as the default for a model field type. You just use the filter_overrides attribute on your FilterSet class. Here's an example: https://gist.github.com/nkryptic/4965223

As to option number 2 above, a Filter already allows setting of the lookup type when it is declared, so I don't see the benefit in adding an override at the filter method also. You can just do the following to force a certain lookup type:

class MyFilterSet(FilterSet):
    username = CharFilter(lookup_type='icontains')
    class Meta:
        model = User

The interaction with a FilterSet is meant to model a ModelForm to a large degree, so a direction I could envision for overriding the default lookup type on a FilterSet might go into the FilterSet's Meta class. Maybe something like:

class MyFilterSet(FilterSet):
    class Meta:
        model = User
        default_lookup_type = 'icontains'

Obviously, a big issue is addressing which filters would adhere to that setting, because for some filters icontains makes no sense. So, how to do this in a way that doesn't confuse the hell out of people trying to use django-filter? They'll wonder which filters use the default_lookup_type and which don't? Not sure how to address the usability issues yet.

The search field mentioned in #75 is similar to what's provided in the Django admin and it's primary use case would be a single search input that filters against multiple model fields. I've worked up an example of it, which you can see here: https://gist.github.com/nkryptic/4727865 although it hasn't been thoroughly tested yet.

It's definitely possible that you could also allow for the derived filters for a model's fields to allow override of the lookup type in Meta.fields, similar to the search field above:

class MyFilterSet(FilterSet):
    class Meta:
        model = User
        # ~FIELD => FIELD__icontains lookup
        fields = ('~username', '~first_name', '~last_name')

As you can see, there are a bunch of possibilities. I think that flexibility is one of the big items to address in django-filter - it should have sensible defaults, but allow for easy overriding at multiple levels.

@duduklein
Copy link
Contributor Author

Thanks for the detailed response. The option currently supported seems great.
I did not know about it, but it's flexible enough and, I agree, very easy to implement.

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

3 participants