Search code examples
pythondjangodjango-4.0

How to access context from a custom django-admin command?


I have been using django.text client to examine the context of some URLs from several unit tests with a code similar to the following:

from django.test import TestCase

class MyTests(TestCase):       

    def example_test(self):
        
        response = self.client.get('/')
        # I can access response.context at this point

Now I am trying to do the same thing from a custom management command but surprisingly this is not working as expected as I can not access the context in the response object.

from django.test import Client

class Command(BaseCommand):

    def handle(self, *args, **kwargs):
        c = Client()
        response = c.get('/')
        # response.context is always None at this point

Is there a way to access the context from a custom management command? (Django 4.0)


Solution

  • The Django test runner DiscoverRunner (and pytest's auto-use fixture django_test_environment) calls setup_test_environment, which replaces Django Template._render. instrumented_test_render sends the template_rendered signal that the Django test Client connects to to populate data, from which it then sets response.context.

    You can do the same in your custom management command:

    from django.template import Template
    from django.test.utils import instrumented_test_render
    
    Template._render = instrumented_test_render
    

    If you want to include all other patches used in tests, you can call setup_test_environment:

    from django.test.utils import setup_test_environment
    
    setup_test_environment()
    

    Among other things, setup_test_environment replaces settings.EMAIL_BACKEND:

    settings.EMAIL_BACKEND = "django.core.mail.backends.locmem.EmailBackend"
    
    ...
    
    mail.outbox = []