Search code examples
pythondjangounit-testing

How to create table during Django tests with managed = False


I have a model with managed = False.

class SampleModel(models.Model):
    apple = models.CharField(max_length=30)
    orange = models.CharField(max_length=30)

    class Meta:
        managed = False

I have a unit test which creates a SampleModel, however when I run the test I get:

DatabaseError: no such table: SAMPLE_SAMPLE_MODEL

The django docs - https://docs.djangoproject.com/en/dev/ref/models/options/#managed documents the following:

For tests involving models with managed=False, it's up to you to ensure the correct tables are created as part of the test setup.

How can I actually "create" the tables during the test setup? Or alternatively, how can I make it so that when I am running tests, this model has "managed = True" for the duration of the test?

In the real application, this model is actually backed by a view in the database. However for the during of the test, I would like to treat this as a table and be able to insert test data in there.


Solution

  • Check out this blog post: http://www.caktusgroup.com/blog/2010/09/24/simplifying-the-testing-of-unmanaged-database-models-in-django/ It describes in detail the creation of a test runner for unmanaged models.

    from django.test.simple import DjangoTestSuiteRunner
    
    
    class ManagedModelTestRunner(DjangoTestSuiteRunner):
        """
        Test runner that automatically makes all unmanaged models in your Django
        project managed for the duration of the test run, so that one doesn't need
        to execute the SQL manually to create them.
        """
        def setup_test_environment(self, *args, **kwargs):
            from django.db.models.loading import get_models
            self.unmanaged_models = [m for m in get_models()
                                     if not m._meta.managed]
            for m in self.unmanaged_models:
                m._meta.managed = True
            super(ManagedModelTestRunner, self).setup_test_environment(*args,
                                                                       **kwargs)
    
        def teardown_test_environment(self, *args, **kwargs):
            super(ManagedModelTestRunner, self).teardown_test_environment(*args,
                                                                          **kwargs)
            # reset unmanaged models
            for m in self.unmanaged_models:
                m._meta.managed = False