Constantinius
Constantinius

Reputation: 35089

Django queries spanning foreign key

I have the following models:

class Collection(models.Model):
    # some fields here ...

class Entry(models.Model):
    collection = models.ForeignKey(Collection, reverse_name="entries")
    start_time = models.DateTimeField()
    end_time = models.DateTimeField()

Now I want to query all Collections that have at least one Entry associated which I do with (quite quirky, I think):

collections_qs = Collection.objects.annotate(
    entry_count=Count('entries')
).filter(entry_count__gt=0)

Which works quite well. But I want to combine this query with a date/time window search given by the two datetimes start and end. What I've come up with was:

if start:
    collections_qs = collections_qs.filter(entries__start_time__gte=start)
if end:
    collections_qs = collections_qs.filter(entriess__end_time__lte=end)

But that just rearranges the order of the returned Collections but not the content. How can I achieve the date/time search (preferably with just one query)?

Upvotes: 1

Views: 224

Answers (1)

Arthur
Arthur

Reputation: 1984

For reverse FK (and ManyToMany fields too), there is a difference between

.filter(a=b, x=y) and .filter(a=b).filter(x=y) (see doc).

What you need when you have both start and end conditions is the filter(.,.) one that will get you the Collections that have at least one Entry that verifies both condition.

Also, Collection.objects.filter(entries__isnull=False).distinct() seems more readable than .annotate(entry_count=Count('entries')).filter(entry_count__gt=0).

Finally, when you have at least one condition on entries, you don't need to have any filter to check for the existence of such entries.

Upvotes: 1

Related Questions