Ticket #600 (closed defect: duplicate)

Opened 4 years ago

Last modified 4 years ago

Adding Boolean field doesn't obey default with SQLite

Reported by: malcolm.box@… Owned by: andrew
Priority: major Milestone: 1.0
Component: databaseapi Version: 0.7.2
Keywords: Cc:

Description

When a migration adds a boolean column to a SQLite database, the default value is not set on existing records.

Trivial example, using SQLite as the database

(example/models.py)

from django.db import models

# Create your models here.

class Example(models.Model):
    data = models.IntegerField()

(commmand)
./manage.py syncdb
./manage.py convert_to_south example
./manage.py shell

Example(data=10).save()

Now change models.py to:

from django.db import models

# Create your models here.

class Example(models.Model):
    data = models.IntegerField()
    flag = models.BooleanField(default=True)
   


(run)
./manage.py schemamigration example --auto
./manage.py migrate example

./manage.py shell

Example.objects.get(pk=1).flag

False

The flag field should be set to True, as this is the specified default. Works correctly on MySQL. The created migration has the right default= line in the db.add_column call.

Change History

comment:1 Changed 4 years ago by andrew

  • Status changed from new to assigned
  • Milestone set to 0.7.3

comment:2 Changed 4 years ago by andrew

  • Milestone changed from 0.7.3 to 1.0

comment:3 Changed 4 years ago by spirt40@…

Bug reason:
SQLite don't have native True and False. In SQLite you must use 1 and 0.

Manual fix:
when auto migration will created... Like this:

db.add_column('node_entry',
  'visible',
  self.gf('django.db.models.fields.BooleanField')(default=True),
  keep_default=False)

Then you must change defaut=True to defaut=1 if you're using just SQLite or like this:

if db.backend_name == "sqlite3":
   default = 1
else:
   default = True
db.add_column('node_entry', 'visible', self.gf('django.db.models.fields.BooleanField')(default=default), keep_default=False)

If you're must often create that type migration, than path South like this:
In file south.db.sqlite3.py if function add_column add this line:

if field.has_default() and isinstance(field.get_default(), bool):
    field.default = 1 if field.get_default() else 0

Than part code will look like this:

# Initialise the field.
field.set_attributes_from_name(name)
if field.has_default() and isinstance(field.get_default(), bool):
    field.default = 1 if field.get_default() else 0
# We add columns by remaking the table; even though SQLite supports 
# adding columns, it doesn't support adding PRIMARY KEY or UNIQUE cols.
self._remake_table(table_name, added={
    field.column: self._column_sql_for_create(table_name, name, field, False),
})

comment:4 Changed 4 years ago by william88@…

Just ran into this problem as well.

I think it is a dup of #578.

comment:5 Changed 4 years ago by andrew

  • Status changed from assigned to closed
  • Resolution set to duplicate

Yep, it's a duplicate, closing as such.

Note: See TracTickets for help on using tickets.