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()
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()