Opened 6 years ago

Closed 3 years ago

Last modified 2 years ago

#15040 closed Bug (fixed)

Boolean fields return 0 and 1 when loaded through select_related

Reported by: homm Owned by: nobody
Component: Database layer (models, ORM) Version: 1.4
Severity: Normal Keywords:
Cc: benjaoming@… Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

This behavior only on mysql. SQLite always return True or False.

Models.py file:

from django.db import models

class BoolModel(models.Model):
    bool = models.BooleanField()

class Parent(models.Model):
    true = models.ForeignKey(BoolModel, related_name='trues')
    false = models.ForeignKey(BoolModel, related_name='falses')

In command line:

./manage.py shell
>>> from ex.models import *
>>> true = BoolModel.objects.create(bool=True)
>>> false = BoolModel.objects.create(bool=False)
>>> parent = Parent.objects.create(true=true, false=false)

>>> parent = Parent.objects.get()
>>> parent.true.bool
True
>>> parent.false.bool
False

>>> parent = Parent.objects.select_related('true', 'false').get()
>>> parent.true.bool
1
>>> parent.false.bool
0

As you can seen, in first case, when parent object loaded without select_related, booleans is booleans.
In second case, when object loaded with select_related, boolens are numbers.

Version 1.2 and 1.3 acts the same.

Attachments (2)

15040.diff (4.1 KB) - added by Ramiro Morales 5 years ago.
Patch, includes tests
15040-anon-test.diff (1.1 KB) - added by Tim Graham 3 years ago.

Download all attachments as: .zip

Change History (19)

comment:1 Changed 6 years ago by Russell Keith-Magee

Triage Stage: UnreviewedAccepted

This is because MySQL has special handling for returning boolean values; in 1.2, we added some callbacks to do the post-processing to ensure values get rectified. However, that rectification is performed with reference to the original model field. When using select_related, the original model obviously isn't being carried along for the ride.

comment:2 Changed 6 years ago by Adam Nelson

Change at #15169 may be related and address this

comment:3 Changed 6 years ago by anonymous

milestone: 1.3
Severity: Normal
Type: Bug

comment:4 Changed 5 years ago by Aymeric Augustin

UI/UX: unset

Change UI/UX from NULL to False.

comment:5 Changed 5 years ago by Aymeric Augustin

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:6 Changed 5 years ago by Ramiro Morales

Has patch: set

Changed 5 years ago by Ramiro Morales

Attachment: 15040.diff added

Patch, includes tests

comment:7 Changed 4 years ago by anonymous

I just spent a ton of time debugging to figure out what this bug is. It causes ModelForms to have checkboxes that are all checked.

comment:8 Changed 4 years ago by benjaoming

Cc: benjaoming@… added

*bump* there is a patch for this! It even contains a very neat set of tests. Can it be merged and the bug closed? :)

comment:9 Changed 4 years ago by anonymous

Version: 1.21.4

In my opinion this is a fairly significant issue. I spent all morning trying to figure out why a ModelForm (which was working perfectly locally on SQLite) had broken checkbox fields when deployed with a mysql backend.

parent = ParentModel.objects.select_related('child').get(pk=id)
# BooleanFields won't work with this form if using MySQL because their values are rendered as ints due to select_related()
child_form = ChildModelForm(instance=parent.child)

If there's no easy fix to this in Django itself I think there should at least be a warning in the documentation letting users know of this issue.

comment:10 Changed 4 years ago by Luke Plant <L.Plant.98@…>

Resolution: fixed
Status: newclosed

In f3a2bcdee906f7ca1434b6275fdc09b3a454cf46:

Fixed #15040 - Boolean fields return 0 and 1 when loaded through select_related

Thanks to homm for the report and ramiro for the patch.

comment:11 Changed 4 years ago by Luke Plant <L.Plant.98@…>

In 142f69eb8c79ea5a54799354231b219f7c53b1cc:

[1.5.x] Fixed #15040 - Boolean fields return 0 and 1 when loaded through select_related

Thanks to homm for the report and ramiro for the patch.

Backport of f3a2bcdee906f7ca1434b6275fdc09b3a454cf46 from master

comment:12 Changed 4 years ago by anonymous

Resolution: fixed
Status: closednew

I am having this problem in 1.5.1 -- 0 when using select related, but False when not. I am using mysql.

comment:13 Changed 4 years ago by anonymous

The problem only occurs when using .defer()

Changed 3 years ago by Tim Graham

Attachment: 15040-anon-test.diff added

comment:14 Changed 3 years ago by Tim Graham

Resolution: fixed
Status: newclosed

@anonymous, please open a new ticket with a test case if you can reproduce the issue on master. I tried the attached test based on your vague description but it passes on master and 1.5.x.

comment:15 Changed 3 years ago by Anssi Kääriäinen

I am pretty sure this one was fixed in #21203 and #21126, both of which got backpatched to 1.5.

comment:16 Changed 2 years ago by Kyle Gibson

I apologise if this isn't the proper place for this comment, but what would it take to get this fix backpatched to 1.4?

comment:17 in reply to:  16 Changed 2 years ago by Carl Meyer

Replying to kylegibson:

I apologise if this isn't the proper place for this comment, but what would it take to get this fix backpatched to 1.4?

I'm afraid it won't be. 1.4 is in security-fix-only mode.

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