|Reported by:||Anssi Kääriäinen||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.4|
|Cc:||Triage Stage:||Ready for checkin|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
qs.none() is currently implemented by returning an EmptyQuerySet which has no-op operators for most of the QuerySet methods.
This approach has several weaknesses:
- Doesn't work well with subclasses of QuerySet (#17271)
- Doesn't work well when Django uses subclasses internally to implement some functionality (values() for example, #15959)
- The EmptyQS doesn't actually work like QuerySet - for example qs.none().filter(nonexisting_field=someval). Also: #19173.
- Code duplication: the EmptyQS has around 150 lines of code duplicating the methods of QS. The duplicated methods just do return self. If you add a method to QS and forget it from EmptyQS strange things can happen.
Problems if removing EmptyQS:
- We have documented it in qs.none() docs. And, I can't see any way to have a deprecation period for this.
- There will be some performance penalty mainly from queryset cloning as the qs.none() methods now actually do something.
I am obviously +1 to just removing the !EmptyQS. The question is if people are relying on isinstance(someqs, EmptyQuerySet) calls in their code. If so, we could add "known_empty" property so that users could check if it is possible for this queryset to return any values.
A work-in-progress patch available from branch akaariai/django/rm_emptyqs.
Change History (6)
comment:5 Changed 4 years ago by
|Patch needs improvement:||unset|
|Triage Stage:||Design decision needed → Ready for checkin|