diff options
Diffstat (limited to 'django')
| -rw-r--r-- | django/core/management/commands/inspectdb.py | 28 | ||||
| -rw-r--r-- | django/db/backends/postgresql/features.py | 1 | ||||
| -rw-r--r-- | django/db/backends/postgresql/introspection.py | 15 |
3 files changed, 27 insertions, 17 deletions
diff --git a/django/core/management/commands/inspectdb.py b/django/core/management/commands/inspectdb.py index cbebd6f60c..5cdd52fccf 100644 --- a/django/core/management/commands/inspectdb.py +++ b/django/core/management/commands/inspectdb.py @@ -23,6 +23,9 @@ class Command(BaseCommand): help='Nominates a database to introspect. Defaults to using the "default" database.', ) parser.add_argument( + '--include-partitions', action='store_true', help='Also output models for partition tables.', + ) + parser.add_argument( '--include-views', action='store_true', help='Also output models for database views.', ) @@ -55,12 +58,15 @@ class Command(BaseCommand): yield 'from %s import models' % self.db_module known_models = [] table_info = connection.introspection.get_table_list(cursor) - tables_to_introspect = ( - options['table'] or - sorted(info.name for info in table_info if options['include_views'] or info.type == 't') - ) - for table_name in tables_to_introspect: + # Determine types of tables and/or views to be introspected. + types = {'t'} + if options['include_partitions']: + types.add('p') + if options['include_views']: + types.add('v') + + for table_name in (options['table'] or sorted(info.name for info in table_info if info.type in types)): if table_name_filter is not None and callable(table_name_filter): if not table_name_filter(table_name): continue @@ -160,7 +166,8 @@ class Command(BaseCommand): field_desc += ' # ' + ' '.join(comment_notes) yield ' %s' % field_desc is_view = any(info.name == table_name and info.type == 'v' for info in table_info) - for meta_line in self.get_meta(table_name, constraints, column_to_field_name, is_view): + is_partition = any(info.name == table_name and info.type == 'p' for info in table_info) + for meta_line in self.get_meta(table_name, constraints, column_to_field_name, is_view, is_partition): yield meta_line def normalize_col_name(self, col_name, used_column_names, is_relation): @@ -257,7 +264,7 @@ class Command(BaseCommand): return field_type, field_params, field_notes - def get_meta(self, table_name, constraints, column_to_field_name, is_view): + def get_meta(self, table_name, constraints, column_to_field_name, is_view, is_partition): """ Return a sequence comprising the lines of code necessary to construct the inner Meta class for the model corresponding @@ -273,7 +280,12 @@ class Command(BaseCommand): columns = [x for x in columns if x is not None] if len(columns) > 1: unique_together.append(str(tuple(column_to_field_name[c] for c in columns))) - managed_comment = " # Created from a view. Don't remove." if is_view else "" + if is_view: + managed_comment = " # Created from a view. Don't remove." + elif is_partition: + managed_comment = " # Created from a partition. Don't remove." + else: + managed_comment = '' meta = [''] if has_unsupported_constraint: meta.append(' # A unique constraint could not be introspected.') diff --git a/django/db/backends/postgresql/features.py b/django/db/backends/postgresql/features.py index 3f43abf9d5..89ff06fdf5 100644 --- a/django/db/backends/postgresql/features.py +++ b/django/db/backends/postgresql/features.py @@ -73,3 +73,4 @@ class DatabaseFeatures(BaseDatabaseFeatures): has_gin_pending_list_limit = property(operator.attrgetter('is_postgresql_9_5')) supports_ignore_conflicts = property(operator.attrgetter('is_postgresql_9_5')) has_phraseto_tsquery = property(operator.attrgetter('is_postgresql_9_6')) + supports_table_partitions = property(operator.attrgetter('is_postgresql_10')) diff --git a/django/db/backends/postgresql/introspection.py b/django/db/backends/postgresql/introspection.py index 85538262cb..3ce88ccfbf 100644 --- a/django/db/backends/postgresql/introspection.py +++ b/django/db/backends/postgresql/introspection.py @@ -42,18 +42,15 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): def get_table_list(self, cursor): """Return a list of table and view names in the current database.""" cursor.execute(""" - SELECT c.relname, c.relkind + SELECT c.relname, + CASE WHEN {} THEN 'p' WHEN c.relkind IN ('m', 'v') THEN 'v' ELSE 't' END FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace - WHERE c.relkind IN ('f', 'm', 'r', 'v') + WHERE c.relkind IN ('f', 'm', 'p', 'r', 'v') AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND pg_catalog.pg_table_is_visible(c.oid) - """) - mapping = {'f': 't', 'm': 'v', 'r': 't', 'v': 'v'} - return [ - TableInfo(row[0], mapping[row[1]]) - for row in cursor.fetchall() if row[0] not in self.ignored_tables - ] + """.format('c.relispartition' if self.connection.features.supports_table_partitions else 'FALSE')) + return [TableInfo(*row) for row in cursor.fetchall() if row[0] not in self.ignored_tables] def get_table_description(self, cursor, table_name): """ @@ -73,7 +70,7 @@ class DatabaseIntrospection(BaseDatabaseIntrospection): JOIN pg_type t ON a.atttypid = t.oid JOIN pg_class c ON a.attrelid = c.oid JOIN pg_namespace n ON c.relnamespace = n.oid - WHERE c.relkind IN ('f', 'm', 'r', 'v') + WHERE c.relkind IN ('f', 'm', 'p', 'r', 'v') AND c.relname = %s AND n.nspname NOT IN ('pg_catalog', 'pg_toast') AND pg_catalog.pg_table_is_visible(c.oid) |
