1

so I haven't been working with Django for too long. I am running into a problem filtering a queryset by the exact name of a string of arrays that is passed into it. Currently, I am filtering the queryset by icontains, which works. For example the current implementation works like this: If I pass in one string called "test" my queryset will be filtered and show deals with tags "test1" "test2" and "test3". This is not what I want. I want to filter by the exact name of the strings that are passed in. So if I have a "test" as one of the strings then my queryset will only search for test, not anything that is contained into it. I've tried multiple implementations, such as switching from icontains to iexact, and exact.

Goal. Filter queryset by array of multiple tags.

old query: values is an array of tags (strings) that are passed in

values = value.replace(" ", "").split(",")
return qs.filter(reduce(operator.or_, (Q(tags__iontains=item) for item in values)))

What I have tried: I have tried passing in the iexact with the list of values like below. I have also tried just passing iexact, and then passing in only one hardcoded string from an array. When I pass in just a string with iexact, I run into an error that says: " Unsupported lookup '' for ArrayField or join on the field not permitted" which makes sense because this is an array.

values = value.replace(" ", "").split(",")
return qs.filter(reduce(operator.or_, (Q(tags__iexact=item) for item in values)))

Has anyone ran into this issue and know a work around? I've been reading through the docs and stack overflow and can't find a solution.

1 Answer 1

1

Assuming this is the PostgreSQL-specific ArrayField - this looks like the overlap lookup. That is, assuming you want results for any of the specified values. It's contains if you want results that have all the specified values.

From the docs:

overlap

Returns objects where the data shares any results with the values passed. Uses the SQL operator &&. For example:

>>> Post.objects.create(name='First post', tags=['thoughts', 'django'])
>>> Post.objects.create(name='Second post', tags=['thoughts'])
>>> Post.objects.create(name='Third post', tags=['tutorial', 'django'])

>>> Post.objects.filter(tags__overlap=['thoughts']) <QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__overlap=['thoughts', 'tutorial']) <QuerySet [<Post: First post>, <Post: Second post>, <Post: Third post>]>


>>> Post.objects.filter(tags__contains=['thoughts']) <QuerySet [<Post: First post>, <Post: Second post>]>

>>> Post.objects.filter(tags__contains=['django']) <QuerySet [<Post: First post>, <Post: Third post>]>

>>> Post.objects.filter(tags__contains=['django', 'thoughts']) <QuerySet [<Post: First post>]>
Sign up to request clarification or add additional context in comments.

3 Comments

With the overlap, how can I make string of arrays dynamic like I have in my example?
tags__overlap=values, same as passing in a filter parameter normally. It expects a sequence so you'll want to split your string as you've shown.
Thanks. Works for what I was looking for i.e. to add filter on BetterArrayField.

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.