#19652 closed Bug (fixed)
Fix for #19524 introduced a backward compatiblity issue with related managers on 1.5.X
Reported by: | Simon Charette | Owned by: | Simon Charette |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.5-beta-1 |
Severity: | Release blocker | Keywords: | none EmptyQuerySet none |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The fix for #19524 which was backported to the 1.5.X branch caused the following regression:
class ObjectQuerySet(models.query.QuerySet): def extra_qs_method(self): pass class ObjectManager(models.Manager): use_for_related_fields = True def get_query_set(self): return ObjectQuerySet(self.model, using=self._db) class RelatedObject(models.Model): pass class Object(models.Model): related = models.ForeignKey(RelatedObject, related_name='objs') objects = ObjectManager() RelatedObject().objs.extra_qs_method()
Raises
AttributeError: 'EmptyQuerySet' object has no attribute 'extra_qs_method'
It works perfectly on master
since QuerySet.none()
returns an instance of the correct class while setting it's underlying's query to empty and on < 1.5.X since prior to this backport there was no instance.pk
check to return an EmptyQuerySet
.
Attachments (1)
Change History (17)
comment:1 by , 12 years ago
Severity: | Normal → Release blocker |
---|
comment:2 by , 12 years ago
comment:3 by , 12 years ago
Isn't it technically possible to have a nullable custom foreign key field? (There could be at most one object with a null pk.)
comment:4 by , 12 years ago
Triage Stage: | Unreviewed → Accepted |
---|
A pk can't be NULL, but if you use to_field, then you could have NULLs on both sides. We definitely want the semantics of SQL's JOIN ON (lhs.fk_val = rhs.to_field). This means that if either/both of those are NULL, then the result is "no match". (SQL's funny trinary boolean logic, NULL = NULL => UNKNOWN.)
If we go an try to change this we will have endless amount of problems.
comment:6 by , 12 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:7 by , 12 years ago
To avoid the NULL = NULL issue, you could just go with a more explicit queryset.filter(Q(pk=1) & ~Q(pk=1))
.
comment:8 by , 12 years ago
The correct approach seems to be to filter using pk__in=[]
which ensures no query is executed.
I am too tired to write a patch today. If anybody else wants to tackle this I won't object...
by , 12 years ago
Attachment: | 0001-Fixed-19652-Fixed-a-regression-introduced-by-9d6d0de.patch added |
---|
comment:10 by , 12 years ago
Has patch: | set |
---|
comment:11 by , 12 years ago
Every use of .none() pre-1.6 will cause this same bug. This is a "feature" of using .none(), and the reason .none() was changed in 1.6. Still, I think it is a good idea to fix this one as this is a regression. Existing code will fail, and the fix is trivial.
I will commit the patch to 1.5.
comment:12 by , 12 years ago
Resolution: | → fixed |
---|---|
Status: | assigned → closed |
comment:16 by , 12 years ago
Component: | ORM aggregation → Database layer (models, ORM) |
---|
The likely fix is to do queryset.filter(pk=None) instead of queryset.none(). User visible effect is the same as what is now done in master.