Opened 8 years ago
Closed 8 years ago
#26983 closed Bug (fixed)
Boolean filter "field__isnull=False" not working with ForeignKey with to_field
Reported by: | weidwonder | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.10 |
Severity: | Normal | Keywords: | queryset |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
models Manager:
class ModelManager(models.Manager): def get_queryset(self): return super(ModelManager, self).get_queryset().filter(parent__isnull=False)
models:
class Category(models.Model): parent = models.ForeignKey('Category', to_field='slug', db_column='parent', max_length=32, blank=True, null=True, related_name='models') name = models.CharField(max_length=50, blank=True, null=True) .... vehicle_models = ModelManager() class Meta: db_table = 'open_category' ordering = ['pinyin']
query:
Category.vehicle_models.filter(slug=model_slug).values('name').query
query's sql output is:
SELECT `open_category`.`name` FROM `open_category` WHERE (`open_category`.`parent` IS NULL AND `open_category`.`slug` = "suteng") ORDER BY `open_category`.`pinyin` ASC
it should be open_category
.parent
IS NOT NULL, I downgrade django to 1.9.9, it works.
Attachments (1)
Change History (18)
comment:1 by , 8 years ago
Description: | modified (diff) |
---|
comment:2 by , 8 years ago
Severity: | Normal → Release blocker |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:3 by , 8 years ago
I simplified the testcase a bit to get rid of some "moving parts".
The key to the failure seems to be the to_field
attribute of the ForeignKey. Without it, the query seems to be generated correctly.
--Edit--
Following the advice of kezabelle on IRC, I placed a PDB trace right before https://github.com/django/django/blob/master/django/db/models/lookups.py#L436 and found out that at this point, the value of self.rhs
is 'False'
, that is the string 'False'
rather than a boolean object, which triggers the wrong branch of the if
statement.
comment:4 by , 8 years ago
Summary: | models.Manager query "filter(field__isnull=False)" not working in 1.10 → Boolean filter "field__isnull=False" not working with ForeignKey with to_field |
---|
follow-up: 6 comment:5 by , 8 years ago
I don't believe that IsNull lookups should be converting their values to the type of the parent field, however the RelatedLookupMixin has useful looking code for ensuring that MultiColSource is handled correctly.
Would the fix for this be as simple as:
class RelatedIsNull(RelatedLookupMixin, IsNull): def get_prep_lookup(self): return self.rhs
?
comment:6 by , 8 years ago
Replying to MatthewWilkes:
I don't believe that IsNull lookups should be converting their values to the type of the parent field, however the RelatedLookupMixin has useful looking code for ensuring that MultiColSource is handled correctly.
Would the fix for this be as simple as:
class RelatedIsNull(RelatedLookupMixin, IsNull): def get_prep_lookup(self): return self.rhs?
return super(RelatedLookupMixin, self).get_prep_lookup()
would be more appropriate.
comment:8 by , 8 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
comment:11 by , 8 years ago
Resolution: | fixed |
---|---|
Status: | closed → new |
This also happens for field_isnull=False
where field
is a ForeignKey
to a model with a CharField
that is primary_key=True
. Again, self.rhs
is converted from False
to 'False
, ie a
bool to a
str`. Reopening as the pach does not fix this.
comment:12 by , 8 years ago
After writing a testcase (available here: https://gist.github.com/lamby/394b712e9e9ff1e868a20e67d4ba482b/raw) "git bisect" told me that it was indeed fixed with the above change. Investigating more, what happened was that I was applying the patch against RelatedIn
instead of RelatedLookupMixin
. Apologies for the noise there.
However, I am still correct in that the bug is not strictly to_field
specific as it affects this primary_key
case. Therefore, I suggest:
- You update the release documentation, etc. to reflect this
- You add my test (or similar) to prevent a regression
In light of this, I am not resolving this ticket so that these action items do not get overlooked.
follow-up: 14 comment:13 by , 8 years ago
Has patch: | unset |
---|---|
Severity: | Release blocker → Normal |
Triage Stage: | Ready for checkin → Accepted |
Could you send a pull request with those items? You can use "Refs #26983 --" in the commit message.
comment:14 by , 8 years ago
comment:17 by , 8 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Hi,
Using the attached testcase based on your description, I managed to confirm the issue and tracked it down to commit 388bb5bd9aa3cd43825cd8a3632a57d8204f875f.
Thanks.