def test_render_multiple_inheritance(self): # Use a custom app cache to avoid polluting the global one. new_app_cache = BaseAppCache() class Book(models.Model): title = models.CharField(max_length=1000) class Meta: app_label = "migrations" app_cache = new_app_cache class Novel(Book): class Meta: app_label = "migrations" app_cache = new_app_cache # First, test rendering individually yet_another_app_cache = BaseAppCache() # We shouldn't be able to render yet with self.assertRaises(ValueError): ModelState.from_model(Novel).render(yet_another_app_cache) # Once the parent model is in the app cache, it should be fine ModelState.from_model(Book).render(yet_another_app_cache) ModelState.from_model(Novel).render(yet_another_app_cache)
def test_render_model_with_multiple_inheritance(self): class Foo(models.Model): class Meta: app_label = "migrations" app_cache = BaseAppCache() class Bar(models.Model): class Meta: app_label = "migrations" app_cache = BaseAppCache() class FooBar(Foo, Bar): class Meta: app_label = "migrations" app_cache = BaseAppCache() app_cache = BaseAppCache() # We shouldn't be able to render yet ms = ModelState.from_model(FooBar) with self.assertRaises(InvalidBasesError): ms.render(app_cache) # Once the parent models are in the app cache, it should be fine ModelState.from_model(Foo).render(app_cache) ModelState.from_model(Bar).render(app_cache) ModelState.from_model(FooBar).render(app_cache)
def render(self): "Turns the project state into actual models in a new AppCache" if self.app_cache is None: self.app_cache = BaseAppCache() for model in self.models.values(): model.render(self.app_cache) return self.app_cache
def test_create(self): """ Tests making a ProjectState from an AppCache """ new_app_cache = BaseAppCache() class Author(models.Model): name = models.CharField(max_length=255) bio = models.TextField() age = models.IntegerField(blank=True, null=True) class Meta: app_label = "migrations" app_cache = new_app_cache unique_together = ["name", "bio"] class AuthorProxy(Author): class Meta: app_label = "migrations" app_cache = new_app_cache proxy = True ordering = ["name"] class Book(models.Model): title = models.CharField(max_length=1000) author = models.ForeignKey(Author) class Meta: app_label = "migrations" app_cache = new_app_cache verbose_name = "tome" db_table = "test_tome" project_state = ProjectState.from_app_cache(new_app_cache) author_state = project_state.models['migrations', 'author'] author_proxy_state = project_state.models['migrations', 'authorproxy'] book_state = project_state.models['migrations', 'book'] self.assertEqual(author_state.app_label, "migrations") self.assertEqual(author_state.name, "Author") self.assertEqual([x for x, y in author_state.fields], ["id", "name", "bio", "age"]) self.assertEqual(author_state.fields[1][1].max_length, 255) self.assertEqual(author_state.fields[2][1].null, False) self.assertEqual(author_state.fields[3][1].null, True) self.assertEqual(author_state.options, {"unique_together": set(("name", "bio"))}) self.assertEqual(author_state.bases, (models.Model, )) self.assertEqual(book_state.app_label, "migrations") self.assertEqual(book_state.name, "Book") self.assertEqual([x for x, y in book_state.fields], ["id", "title", "author"]) self.assertEqual(book_state.fields[1][1].max_length, 1000) self.assertEqual(book_state.fields[2][1].null, False) self.assertEqual(book_state.options, {"verbose_name": "tome", "db_table": "test_tome"}) self.assertEqual(book_state.bases, (models.Model, )) self.assertEqual(author_proxy_state.app_label, "migrations") self.assertEqual(author_proxy_state.name, "AuthorProxy") self.assertEqual(author_proxy_state.fields, []) self.assertEqual(author_proxy_state.options, {"proxy": True, "ordering": ["name"]}) self.assertEqual(author_proxy_state.bases, ("migrations.author", ))
def test_render_project_dependencies(self): """ Tests that the ProjectState render method correctly renders models to account for inter-model base dependencies. """ new_app_cache = BaseAppCache() class A(models.Model): class Meta: app_label = "migrations" app_cache = new_app_cache class B(A): class Meta: app_label = "migrations" app_cache = new_app_cache class C(B): class Meta: app_label = "migrations" app_cache = new_app_cache class D(A): class Meta: app_label = "migrations" app_cache = new_app_cache class E(B): class Meta: app_label = "migrations" app_cache = new_app_cache proxy = True class F(D): class Meta: app_label = "migrations" app_cache = new_app_cache proxy = True # Make a ProjectState and render it project_state = ProjectState() project_state.add_model_state(ModelState.from_model(A)) project_state.add_model_state(ModelState.from_model(B)) project_state.add_model_state(ModelState.from_model(C)) project_state.add_model_state(ModelState.from_model(D)) project_state.add_model_state(ModelState.from_model(E)) project_state.add_model_state(ModelState.from_model(F)) final_app_cache = project_state.render() self.assertEqual(len(final_app_cache.get_models()), 6) # Now make an invalid ProjectState and make sure it fails project_state = ProjectState() project_state.add_model_state(ModelState.from_model(A)) project_state.add_model_state(ModelState.from_model(B)) project_state.add_model_state(ModelState.from_model(C)) project_state.add_model_state(ModelState.from_model(F)) with self.assertRaises(InvalidBasesError): project_state.render()
def test_render_multiple_inheritance(self): # Use a custom app cache to avoid polluting the global one. new_app_cache = BaseAppCache() class Book(models.Model): title = models.CharField(max_length=1000) class Meta: app_label = "migrations" app_cache = new_app_cache class Novel(Book): class Meta: app_label = "migrations" app_cache = new_app_cache yet_another_app_cache = BaseAppCache() ModelState.from_model(Novel).render(yet_another_app_cache)
class M(models.Model): foo = models.IntegerField() bar = models.IntegerField() baz = models.IntegerField() Meta = type(str('Meta'), (), { 'unique_together': unique_together, 'app_cache': BaseAppCache() })
def test_dynamic_load(self): """ Makes a new model at runtime and ensures it goes into the right place. """ old_models = cache.get_models(cache.get_app("app_cache")) # Construct a new model in a new app cache body = {} new_app_cache = BaseAppCache() meta_contents = { 'app_label': "app_cache", 'app_cache': new_app_cache, } meta = type("Meta", tuple(), meta_contents) body['Meta'] = meta body['__module__'] = TotallyNormal.__module__ temp_model = type("SouthPonies", (models.Model,), body) # Make sure it appeared in the right place! self.assertEqual( old_models, cache.get_models(cache.get_app("app_cache")), ) self.assertEqual(new_app_cache.get_model("app_cache", "SouthPonies"), temp_model)
def render(self): "Turns the project state into actual models in a new AppCache" if self.app_cache is None: self.app_cache = BaseAppCache() # We keep trying to render the models in a loop, ignoring invalid # base errors, until the size of the unrendered models doesn't # decrease by at least one, meaning there's a base dependency loop/ # missing base. unrendered_models = list(self.models.values()) while unrendered_models: new_unrendered_models = [] for model in unrendered_models: try: model.render(self.app_cache) except InvalidBasesError: new_unrendered_models.append(model) if len(new_unrendered_models) == len(unrendered_models): raise InvalidBasesError("Cannot resolve bases for %r" % new_unrendered_models) unrendered_models = new_unrendered_models return self.app_cache
def test_render_model_inheritance(self): class Book(models.Model): title = models.CharField(max_length=1000) class Meta: app_label = "migrations" app_cache = BaseAppCache() class Novel(Book): class Meta: app_label = "migrations" app_cache = BaseAppCache() # First, test rendering individually app_cache = BaseAppCache() # We shouldn't be able to render yet ms = ModelState.from_model(Novel) with self.assertRaises(InvalidBasesError): ms.render(app_cache) # Once the parent model is in the app cache, it should be fine ModelState.from_model(Book).render(app_cache) ModelState.from_model(Novel).render(app_cache)
from django.db import models from django.db.models.loading import BaseAppCache # Because we want to test creation and deletion of these as separate things, # these models are all inserted into a separate AppCache so the main test # runner doesn't syncdb them. new_app_cache = BaseAppCache() class Author(models.Model): name = models.CharField(max_length=255) height = models.PositiveIntegerField(null=True, blank=True) class Meta: app_cache = new_app_cache class AuthorWithM2M(models.Model): name = models.CharField(max_length=255) class Meta: app_cache = new_app_cache class Book(models.Model): author = models.ForeignKey(Author) title = models.CharField(max_length=100, db_index=True) pub_date = models.DateTimeField() # tags = models.ManyToManyField("Tag", related_name="books")
class Meta: app_label = "migrations" app_cache = BaseAppCache()
class Meta: app_cache = BaseAppCache() app_label = "migrations" db_table = "django_migrations"
def _remake_table(self, model, create_fields=[], delete_fields=[], alter_fields=[], rename_fields=[], override_uniques=None): """ Shortcut to transform a model from old_model into new_model """ # Work out the new fields dict / mapping body = dict((f.name, f) for f in model._meta.local_fields) mapping = dict((f.column, f.column) for f in model._meta.local_fields) # If any of the new or altered fields is introducing a new PK, # remove the old one restore_pk_field = None if any(f.primary_key for f in create_fields) or any(n.primary_key for o, n in alter_fields): for name, field in list(body.items()): if field.primary_key: field.primary_key = False restore_pk_field = field if field.auto_created: del body[name] del mapping[field.column] # Add in any created fields for field in create_fields: body[field.name] = field # Add in any altered fields for (old_field, new_field) in alter_fields: del body[old_field.name] del mapping[old_field.column] body[new_field.name] = new_field mapping[new_field.column] = old_field.column # Remove any deleted fields for field in delete_fields: del body[field.name] del mapping[field.column] # Work inside a new AppCache app_cache = BaseAppCache() # Construct a new model for the new state meta_contents = { 'app_label': model._meta.app_label, 'db_table': model._meta.db_table + "__new", 'unique_together': model._meta.unique_together if override_uniques is None else override_uniques, 'app_cache': app_cache, } meta = type("Meta", tuple(), meta_contents) body['Meta'] = meta body['__module__'] = model.__module__ temp_model = type(model._meta.object_name, model.__bases__, body) # Create a new table with that format self.create_model(temp_model) # Copy data from the old table field_maps = list(mapping.items()) self.execute("INSERT INTO %s (%s) SELECT %s FROM %s" % ( self.quote_name(temp_model._meta.db_table), ', '.join(x for x, y in field_maps), ', '.join(y for x, y in field_maps), self.quote_name(model._meta.db_table), )) # Delete the old table self.delete_model(model) # Rename the new to the old self.alter_db_table(model, temp_model._meta.db_table, model._meta.db_table) # Run deferred SQL on correct table for sql in self.deferred_sql: self.execute( sql.replace(temp_model._meta.db_table, model._meta.db_table)) self.deferred_sql = [] # Fix any PK-removed field if restore_pk_field: restore_pk_field.primary_key = True
class Meta: # Disable auto loading of this model as we load it on our own app_cache = BaseAppCache() verbose_name = 'úñí©óðé µóðéø' verbose_name_plural = 'úñí©óðé µóðéøß'
class Meta: # Disable auto loading of this model as we load it on our own app_cache = BaseAppCache()
class Meta: verbose_name = 'a model created on the fly' app_label = 'my_great_app' app_cache = BaseAppCache()