Question

I have a Django application with a Publication model and a Tag model. Each publication has one or more Tags associated with it. I want to query the database with a set of two Tags and have returned only publications that have BOTH of those tags.

I cannot seem to find the syntax for this although I am certain it is readily available - I suppose I am not using the correct language to search. What I have tried already is:

pubs_for_tags = Publication.objects.filter(tags__title__istartswith=q, tags__title__istartswith=q2)

But this gives me an error "keyword argument repeated". I've also tried some variations of this, but nothing has worked so far. Can someone enlighten me on the correct syntax for this?

Was it helpful?

Solution

pubs_for_tags = Publication.objects.filter(tags__title__istartswith=q).filter( tags__title__istartswith=q2)


or

pubs_for_tags = Publication.objects.filter(Q(tags__title__istartswith=q), Q( tags__title__istartswith=q2))

OTHER TIPS

I know this is old, but I just ran into the same problem and realized it points at an (as far as I know) undocumented aspect of using Django filters across one-to-many or many-to-many relations. Two conditions made within the same filter apply to the same related object. Two conditions made in separate filters can match two separate related objects.

Another way to think of this is that each complete filter only looks at a single related object at a time, removing a result if all of its related objects fail that filter. Given this, it is extremely rare that you would want two conditions in the same filter using the same keyword.

Consider the following query:

pubs_for_tags = Publication.objects.filter(
    tags__title__istartswith=q,
    tags__title__iendswith=q2
    )

vs

pubs_for_tags = Publication.objects.filter(
    tags__title__istartswith=q,
    ).filter(
    tags__title__iendswith=q2
    )

The first query finds publications that each have a single tag that both starts with q and ends with q2. When the keyword is the same (note I used two different keywords in my example), you also get the "keyword argument repeated" error.

The second query finds publications that each have a tag that starts with q and have a tag that ends with q2, but it can be two different tags for each publication. From your post, it sounds like this is very close to what you need (just change the "iendswith" to "istartswith"). The only part that could break is if q and q2 are the same or one is a substring of the other. In that instance, a publication could have a single tag that would satisfy both conditions.

Note that all this means using Q objects (which nnmware and Gaurav gave as a possible solution) will not give you the result you want. Having two Q objects in a single filter forces behaviour the same as the first example, but gets around the "keyword argument repeated" error.

pubs_for_tags = Publication.objects.filter(
    Q(tags__title__istartswith=q) & Q(tags__title__istartswith=q2)
    )

try this

from django.db.models import Q
pubs_for_tags = Publication.objects.filter(Q(tags__title__istartswith=q) & Q( tags__title__istartswith=q2))

check this link

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top