diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py
index 936d5e8..b71bf01 100644
a
|
b
|
class Command(NoArgsCommand):
|
108 | 108 | # Add 'null' and 'blank', if the 'null_ok' flag was present in the |
109 | 109 | # table description. |
110 | 110 | if row[6]: # If it's NULL... |
111 | | extra_params['blank'] = True |
112 | | if not field_type in ('TextField(', 'CharField('): |
113 | | extra_params['null'] = True |
| 111 | if field_type == 'BooleanField(': |
| 112 | field_type = 'NullBooleanField(' |
| 113 | else: |
| 114 | extra_params['blank'] = True |
| 115 | if not field_type in ('TextField(', 'CharField('): |
| 116 | extra_params['null'] = True |
114 | 117 | |
115 | 118 | field_desc = '%s = models.%s' % (att_name, field_type) |
116 | 119 | if extra_params: |
diff --git a/django/db/backends/sqlite3/introspection.py b/django/db/backends/sqlite3/introspection.py
index 1df4c18..6075ef8 100644
a
|
b
|
class FlexibleFieldLookupDict(object):
|
45 | 45 | return ('CharField', {'max_length': size}) |
46 | 46 | raise KeyError |
47 | 47 | |
| 48 | def values(self): |
| 49 | return self.base_data_types_reverse.values() |
| 50 | |
| 51 | |
48 | 52 | class DatabaseIntrospection(BaseDatabaseIntrospection): |
49 | 53 | data_types_reverse = FlexibleFieldLookupDict() |
50 | 54 | |
diff --git a/tests/regressiontests/inspectdb/models.py b/tests/regressiontests/inspectdb/models.py
index 4a66214..9125156 100644
a
|
b
|
from django.db import models
|
3 | 3 | |
4 | 4 | class People(models.Model): |
5 | 5 | name = models.CharField(max_length=255) |
| 6 | is_admin = models.BooleanField() |
| 7 | has_family = models.NullBooleanField() |
6 | 8 | |
7 | 9 | class Message(models.Model): |
8 | 10 | from_field = models.ForeignKey(People, db_column='from_id') |
diff --git a/tests/regressiontests/inspectdb/tests.py b/tests/regressiontests/inspectdb/tests.py
index 028d263..46b74d0 100644
a
|
b
|
from __future__ import unicode_literals
|
3 | 3 | from django.core.management import call_command |
4 | 4 | from django.db import connection |
5 | 5 | from django.test import TestCase, skipUnlessDBFeature |
| 6 | from django.test.testcases import _deferredSkip |
6 | 7 | from django.utils.six import StringIO |
7 | 8 | |
8 | 9 | |
| 10 | def skipUnlessIntrospectBoolean(): |
| 11 | return _deferredSkip( |
| 12 | lambda: 'BooleanField' not in connection.introspection.data_types_reverse.values(), |
| 13 | "Database cannot introspect boolean fields") |
| 14 | |
| 15 | |
9 | 16 | class InspectDBTestCase(TestCase): |
10 | 17 | |
| 18 | @skipUnlessIntrospectBoolean() |
| 19 | def test_boolean_inspection(self): |
| 20 | out = StringIO() |
| 21 | # Lets limit the introspection to the test target table |
| 22 | call_command('inspectdb', |
| 23 | table_name_filter=lambda tn:tn=='inspectdb_people', |
| 24 | stdout=out) |
| 25 | output = out.getvalue() |
| 26 | self.assertIn("is_admin = models.BooleanField()", output) |
| 27 | self.assertIn("has_family = models.NullBooleanField()", output) |
| 28 | |
11 | 29 | def test_stealth_table_name_filter_option(self): |
12 | 30 | out = StringIO() |
13 | 31 | # Lets limit the introspection to tables created for models of this |