From 25486b35c979259feee14526b2d78b7be7cfd5a1 Mon Sep 17 00:00:00 2001 From: Derek Anderson Date: Mon, 21 Nov 2016 12:16:59 -0600 Subject: [PATCH] fix for tries to create table referencing foreign key when table doesn't exist #3 --- peeweedbevolve.py | 22 +++++++++++++++------- test.py | 11 +++++++++++ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/peeweedbevolve.py b/peeweedbevolve.py index 67fb7e0..c77c87a 100644 --- a/peeweedbevolve.py +++ b/peeweedbevolve.py @@ -17,7 +17,7 @@ # peewee doesn't do defaults in the database - doh! DIFF_DEFAULTS = False -__version__ = '0.4.5' +__version__ = '0.4.6' try: @@ -26,10 +26,15 @@ unicode = lambda s: str(s) -def sort_by_fk_deps(table_names): +def mark_fks_as_deferred(table_names): + add_fks = [] table_names_to_models = {cls._meta.db_table:cls for cls in all_models.keys() if cls._meta.db_table in table_names} - models = pw.sort_models_topologically(table_names_to_models.values()) - return [model._meta.db_table for model in models] + for model in table_names_to_models.values(): + for field in model._meta.sorted_fields: + if isinstance(field, pw.ForeignKeyField): + add_fks.append(field) + field.deferred = True + return add_fks def calc_table_changes(existing_tables): existing_tables = set(existing_tables) @@ -51,8 +56,8 @@ def calc_table_changes(existing_tables): adds.remove(to_add) deletes.remove(a) break - adds = sort_by_fk_deps(adds) - return adds, deletes, renames + add_fks = mark_fks_as_deferred(adds) + return adds, add_fks, deletes, renames def is_postgres(db): return db.__class__.__name__ in ['PostgresqlDatabase','PooledPostgresqlDatabase','PostgresqlExtDatabase'] @@ -311,9 +316,12 @@ def calc_changes(db): qc = db.compiler() to_run = [] - table_adds, table_deletes, table_renames = calc_table_changes(existing_tables) + table_adds, add_fks, table_deletes, table_renames = calc_table_changes(existing_tables) table_renamed_from = {v:k for k,v in table_renames.items()} to_run += [qc.create_table(table_names_to_models[tbl]) for tbl in table_adds] + for field in add_fks: + op = qc._create_foreign_key(field.model_class, field) + to_run.append(qc.parse_node(op)) for k,v in table_renames.items(): ops = migrator.rename_table(k,v, generate=True) if not hasattr(ops, '__iter__'): ops = [ops] # sometimes pw return arrays, sometimes not diff --git a/test.py b/test.py index da58f09..3067f0f 100644 --- a/test.py +++ b/test.py @@ -474,6 +474,17 @@ class Meta: self.evolve_and_check_noop() self.assertEqual(SomeModel.select().first().some_field, 'woot') + def test_circular_deps(self): + class SomeModel(pw.Model): + some_model2 = pw.ForeignKeyField(pw.DeferredRelation('SomeModel2')) + class Meta: + database = self.db + class SomeModel2(pw.Model): + some_model = pw.ForeignKeyField(SomeModel) + class Meta: + database = self.db + self.evolve_and_check_noop() + ## SQLite doesn't work