Reputation: 4352
The model is something like
class Product(BaseModel):
name = models.CharField(db_column='name', max_length=200, blank=False, null=False, unique=True)
View is
class ProductViewSet(BaseViewSet):
queryset = Product.objects.all()
...
filterset_class = ProductFilter
The filter is
class ProductFilter(django_filters.FilterSet):
search = django_filters.CharFilter(field_name='name', lookup_expr='icontains')
class Meta:
model = Product
fields = []
Now.. if the name field has a value something like "This is a/sample
" and search text is "asample
". I would like to return that row.
Thanks in advance.
Upvotes: 1
Views: 2335
Reputation: 67
Use PostGreSQL, which currently supports the 'unaccent' extension. This makes searching for 'año' possible when only typing 'ano'.
Best thing is, you can decide whether to use this extension for every filter by, for example using
Person.objects.filter(first_name__unaccent__icontains=search)
Switch your database to PostgreSQL and add the unaccent extension as follows:
Part of answer from @SaeX in another thread: How can I activate the unaccent extension on an already existing model
A migration file needs to be manually made and applied.
./manage.py makemigrations myapp --empty
from django.contrib.postgres.operations import UnaccentExtension
class Migration(migrations.Migration):
dependencies = [
(<snip>)
]
operations = [
UnaccentExtension()
]
./manage.py migrate.
If you'd get following error during that last step:
django.db.utils.ProgrammingError: permission denied to create extension "unaccent"
HINT: Must be superuser to create this extension.
... then temporarily allow superuser rights to your user by performing postgres# ALTER ROLE <user_name> SUPERUSER; and its NOSUPERUSER counterpart. pgAdminIII can do this, too.
Now enjoy the unaccent functionality using Django:
>>> Person.objects.filter(first_name__unaccent=u"Helène")
[<Person: Michels Hélène>]
Again, part of this answer belongs to @SaeX
IMPORTANT
But for me his answer still didn't work, so don't forget to
add the line django.contrib.postgres
in INSTALLED_APPS (settings.py)
Upvotes: 1
Reputation: 997
If the question is only for one special character ie. '/' then you can create a custom filter method with Replace like this :
class ProductFilter(django_filters.FilterSet):
def filter_without_special_chars(self, queryset, field, value):
return queryset.annotate(search_field=Replace('name', Value('/'), Value('')).filter(search_field__icontains=value)
search = django_filters.CharFilter(method='filter_without_special_chars')
class Meta:
model = Product
fields = []
You can also do this for multiple special characters BUT it won't be the optimal solution, I would suggest you user ElasticSearch (or something similar) for that.
For multiple char replacement the function would look something like this :
def filter_without_special_chars(self, queryset, field, value):
return queryset.annotate(sf1=Replace('name', Value('!'), Value('')),
sf2=Replace('sf1', Value('%'), Value(''))).filter(sf2__icontains=value)
Upvotes: 2