class ModelSchema(models.Model): name = models.CharField(max_length=32, unique=True) def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._registry = ModelRegistry(self.app_label) self._initial_name = self.name initial_model = self.get_registered_model() self._schema_editor = ModelSchemaEditor(initial_model) def save(self, **kwargs): super().save(**kwargs) cache.update_last_modified(self.model_name) cache.update_last_modified(self.initial_model_name) self._schema_editor.update_table(self._factory.make_model()) self._initial_name = self.name def delete(self, **kwargs): self._schema_editor.drop_table(self.as_model()) self._factory.destroy_model() cache.clear_last_modified(self.initial_model_name) super().delete(**kwargs) def get_registered_model(self): return self._registry.get_model(self.model_name) @property def _factory(self): return ModelFactory(self) @property def app_label(self): return config.dynamic_models_app_label() @property def model_name(self): return self.get_model_name(self.name) @property def initial_model_name(self): return self.get_model_name(self._initial_name) @classmethod def get_model_name(cls, name): return name.title().replace(" ", "") @property def db_table(self): parts = (self.app_label, slugify(self.name).replace("-", "_")) return "_".join(parts) def as_model(self): return self._factory.get_model()
def test_update_table_alters_if_table_exists(self, initial_model, changed_model): assert db_table_exists("tests_initialmodel") assert not db_table_exists("tests_changedmodel") ModelSchemaEditor(initial_model).update_table(changed_model) assert db_table_exists("tests_changedmodel") assert not db_table_exists("tests_initialmodel")
def initial_field_table(self, initial_model): ModelSchemaEditor().create_table(initial_model)
def bare_table(self, bare_model): ModelSchemaEditor().create_table(bare_model)
def test_drop_table(self, initial_model): assert db_table_exists("tests_initialmodel") ModelSchemaEditor().drop_table(initial_model) assert not db_table_exists("tests_initialmodel")
def test_update_table_creates_if_not_exists(self, initial_model): assert not db_table_exists("tests_initialmodel") ModelSchemaEditor().update_table(initial_model) assert db_table_exists("tests_initialmodel")
def test_alter_table(self, initial_model, changed_model): assert db_table_exists('tests_initialmodel') assert not db_table_exists('tests_changedmodel') ModelSchemaEditor(initial_model).alter_table(changed_model) assert db_table_exists('tests_changedmodel') assert not db_table_exists('tests_initialmodel')
def test_create_table(self, initial_model): assert not db_table_exists('tests_initialmodel') ModelSchemaEditor().create_table(initial_model) assert db_table_exists('tests_initialmodel')
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._registry = ModelRegistry(self.app_label) self._initial_name = self.name initial_model = self.get_registered_model() self._schema_editor = ModelSchemaEditor(initial_model)
class ModelSchema(models.Model): name = models.CharField(max_length=32, unique=True) _modified = models.DateTimeField(auto_now=True) _cache = LastModifiedCache() def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self._registry = ModelRegistry(self.app_label) self._initial_name = self.name initial_model = self.get_registered_model() self._schema_editor = ModelSchemaEditor(initial_model) def save(self, **kwargs): super().save(**kwargs) self.last_modified = self._modified self._schema_editor.update_table(self._factory.make_model()) def delete(self, **kwargs): self._schema_editor.drop_table(self.as_model()) self._factory.destroy_model() del self.last_modified super().delete(**kwargs) @property def last_modified(self): return self._cache.get(self) @last_modified.setter def last_modified(self, timestamp): self._cache.set(self, timestamp) @last_modified.deleter def last_modified(self): self._cache.delete(self) def get_registered_model(self): return self._registry.get_model(self.model_name) def is_current_schema(self): return self._modified >= self.last_modified def is_current_model(self, model): if model._schema.pk != self.pk: raise ValueError("Can only be called on a model of this schema") return model._declared >= self.last_modified @property def _factory(self): return ModelFactory(self) @property def app_label(self): return config.dynamic_models_app_label() @property def model_name(self): return self.get_model_name(self.name) @property def initial_model_name(self): return self.get_model_name(self._initial_name) @classmethod def get_model_name(cls, name): return name.title().replace(' ', '') @property def db_table(self): parts = (self.app_label, slugify(self.name).replace('-', '_')) return '_'.join(parts) def as_model(self): return self._factory.get_model()
def test_model_is_changed(self, initial_model, changed_model): assert ModelSchemaEditor(initial_model).has_changed(changed_model)
def test_model_is_not_changed(self, initial_model): assert not ModelSchemaEditor(initial_model).has_changed(initial_model)