5

I am given a list like so

a = [1, 2, 3, 4]

This list matches the id's stored in a django model we will call Books.

I am trying to return a queryset of Books with the id's in the list. I am thinking of using Q objects and grab them by doing something like this

Books.objects.filter(Q(id = 1) | Q(id=2) | Q(id=3) | Q(id=4))

Now i would just use the index like this:

Books.objects.filter(Q(id = a[0]) | Q(id=a[1]) | Q(id=a[2]) | Q(id=a[3]))

BUT, These list will be varying in length up to around 30 and hardcoding the index wont work, and hardcoding the query won't satisfy the varying length of lists.

Is it possible to go this route? And if so, how can I accomplish returning the books with the id's that match the list?

2 Answers 2

10

You should use the __in lookup [Django-doc] here:

Books.objects.filter(pk__in=a)

As the documentation says:

In a given iterable; often a list, tuple, or queryset. It’s not a common use case, but strings (being iterables) are accepted.

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

8 Comments

If you could, how could i accomplish this with a list of strings instead of integers?
@Mfreeman: the same way, just a = ['foo', 'bar'], for example Books.objects.filter(title__in=a).
Are you sure? in the docs it shows Entry.objects.filter(id__in=[1, 3, 4]) Entry.objects.filter(headline__in='abc') as equivalents to these sql commands SELECT ... WHERE id IN (1, 3, 4); SELECT ... WHERE headline IN ('a', 'b', 'c');
@Mfreeman: I'm quite sure, are you sure that the list contains the exact same string (no leading/trailing spaces, etc.)? Did you pass it as a list of strings, not a single string.
@MFreeman: well you can check the query it generates with print(Books.objects.filter(...).query). But I'm actually really surprised.
|
2

For a simple case, use __in lookup as per the answer above

However, Q objects connected with | is not magic syntax, so it ought to be possible to build chains of them using loops, like

qlst = []
for x in some_iterable
    qel = Q( something based on x)
    qlst.append(qel)
if len(qlst) == 0:
    # oops -- must handle somehow, or code below will crash
filter = qlst[0]
for qel in qlst[1:]:
    filter = filter | qel

queryset = Books.objects.filter( filter)

Caveat: I've never actually needed to try this.

Comments

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.