Jessica Chambers
Jessica Chambers

Reputation: 1326

Django: Trying to return sum of objects between two dates, instead returns sum of all objects

I have a Django table containing events, each marked with a timestamp. For testing purposes I put in some future dates (2020), but instead of returning the count of events between the two dates (0), this returns the sum of all of the events since the beginning of the DB (5).

The Django request is as follows:

queryset = queryset.annotate(
    value=aggregate_operation(
        f"{MESSAGEMODEL_ATTRIBUTE_NAME_IN_DEVICEMODEL}__press_count", filter=timestamp_filter
        )
    ).values(DEVICE_REFERENCE_ATTRIBUTE_NAME, "value")

I printed all of the variables involved:

filter =  (OR: ('messages__timestamp__gte', datetime.datetime(2020, 1, 2, 16, 9, 5, tzinfo=<django.utils.timezone.FixedOffset object at 0x7fe619ed0c18>)), ('messages__timestamp__lte', datetime.datetime(2020, 8, 30, 16, 9, 5, tzinfo=<django.utils.timezone.FixedOffset object at 0x7fe619e9bf60>)))
value =  Sum(F(messages__press_count), filter=(OR: ('messages__timestamp__gte', datetime.datetime(2020, 1, 2, 16, 9, 5, tzinfo=<django.utils.timezone.FixedOffset object at 0x7fe619ed0c18>)), ('messages__timestamp__lte', datetime.datetime(2020, 8, 30, 16, 9, 5, tzinfo=<django.utils.timezone.FixedOffset object at 0x7fe619e9bf60>))))
queryset =  <QuerySet [{'name': '001 - CHANTIER1 - LIVRAISONS', 'value': 5}]>

the timestamp filter is defined as so, both to_timestamp and from timestamp are defined in this case:

timestamp_filter = Q()
if from_timestamp:
    timestamp_filter |= Q(
                    **{f"{MESSAGEMODEL_ATTRIBUTE_NAME_IN_DEVICEMODEL}__{TIMESTAMP_FIELD_NAME}__gte": from_timestamp}
                )
if to_timestamp:
    timestamp_filter |= Q(
                    **{f"{MESSAGEMODEL_ATTRIBUTE_NAME_IN_DEVICEMODEL}__{TIMESTAMP_FIELD_NAME}__lte": to_timestamp}
                )

Why isn't this request behaving as expected?

EDIT: all my requests return the sum total since the beginning of the DB, despite the dates they are given

Upvotes: 0

Views: 87

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 600041

You need &= not |=.

As it is, your query is "everything that is after 2020-01-02 OR before 2020-08-30", which matches everything. Consider 2019-01-01, which should be outside the range; it is not after 2020-01-02, so it fails the first condition, but it is before 2020-08-30, so it matches the second condition, and the overall filter is True.

Using & ensures that both conditions match.

Upvotes: 1

Related Questions