Opened 10 years ago

Last modified 10 years ago

#23662 closed Cleanup/optimization

QuerySet __nonzero__, __len__ cause queryset evaluation — at Version 3

Reported by: Alexey Smishlayev Owned by: nobody
Component: Database layer (models, ORM) Version: 1.7
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: yes

Description (last modified by Akis Kesoglou)

Current implementation: https://github.com/django/django/blob/master/django/db/models/query.py

class QuerySet(object):
    ...
    def __nonzero__(self):
        self._fetch_all()
        return bool(self._result_cache)
    ...
    def __len__(self):
        self._fetch_all()
        return len(self._result_cache)

These methods call self._fetch_all(), thus evaluating the queryset. Although, this behaviour is documented, it is not obvious.

It seems logical to evaluate queryset, when casting it to a list() or iterating over it, but these particular cases have nothing to do with the queryset contents. There exist specific lazy methods (QuerySet.exists() and QuerySet.count() respectively) which, IMHO, should be used for the magic method implementation.

If I already have fetched the results of a queryset, I'm okay to call __len__() on them, but if they haven't been retrieved yet, I'd rather use SQL COUNT() instead. That is exactly, what QuerySet.count() does. The same goes for the __nonzero__() and exists().

Change History (4)

by Alexey Smishlayev, 10 years ago

Attachment: Fix#23662.patch added

comment:1 by Alexey Smishlayev, 10 years ago

Component: UncategorizedDatabase layer (models, ORM)
Has patch: set
Type: UncategorizedCleanup/optimization
UI/UX: set

comment:2 by Akis Kesoglou, 10 years ago

Description: modified (diff)

Edited bug description to properly format example code

comment:3 by Akis Kesoglou, 10 years ago

Description: modified (diff)

Ditto

Note: See TracTickets for help on using tickets.
Back to Top