Opened 4 years ago

Closed 21 months ago

Last modified 8 months 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 3 years ago.
Patch, includes tests
15040-anon-test.diff (1.1 KB) - added by timo 21 months ago.

Download all attachments as: .zip

Change History (19)

comment:1 Changed 4 years ago by russellm

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

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 4 years ago by adamnelson

Change at #15169 may be related and address this

comment:3 Changed 4 years ago by anonymous

  • milestone 1.3 deleted
  • Severity set to Normal
  • Type set to Bug

comment:4 Changed 3 years ago by aaugustin

  • UI/UX unset

Change UI/UX from NULL to False.

comment:5 Changed 3 years ago by aaugustin

  • Easy pickings unset

Change Easy pickings from NULL to False.

comment:6 Changed 3 years ago by ramiro

  • Has patch set

Changed 3 years ago by ramiro

Patch, includes tests

comment:7 Changed 3 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 3 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 3 years ago by anonymous

  • Version changed from 1.2 to 1.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 3 years ago by Luke Plant <L.Plant.98@…>

  • Resolution set to fixed
  • Status changed from new to closed

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 3 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 2 years ago by anonymous

  • Resolution fixed deleted
  • Status changed from closed to new

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 2 years ago by anonymous

The problem only occurs when using .defer()

Changed 21 months ago by timo

comment:14 Changed 21 months ago by timo

  • Resolution set to fixed
  • Status changed from new to closed

@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 21 months ago by akaariai

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

comment:16 follow-up: Changed 8 months ago by 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?

comment:17 in reply to: ↑ 16 Changed 8 months ago by carljm

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