pythondjangodependency-injection

Can dependency injection be used with django?


I am very popular with using the technique of dependency injection to decouple my code. This would typically involve providing an object with functionality, into the constructor of it's dependent.

For the first time, I am using django to make a web api (with a database of objects attached). I intended to inject an elaborate dependency into the otherwise simple method. (in my case it was functionality to interpret messages coming from RabbitMQ exchanges, but my minimal example is just interpreting a generic message as a site-dependent dictionary).

However in django everything seems to be autogenerated from either static methods or the definition of classes, I couldn't find where anything was actually instantiated or customisable to push the dependency in.

Is the technique and the django framework just incompatible or am I missing something?

Code so far

(minimal example recreation, not actual code)

in urs.py:

urlpatterns = [
    path("run/", views.run),
]

in views.py

def run(request):
    interpreter = AbstractDataInterpreter() #This is the object I want to inject
    data = interpreter.interpret(request)
    return JsonResponse(data, safe=False)

I have a test class TestDataInterpreter to use for testing.

I have a class CustomDataInterpreter custom for my domain/ecosystem.

I plan for for other interpreters on different deployments going forward.

But I can't find the mechanism to actually inject an interpreter into the run command on the different deployments.


Solution

  • I found a good solution eventually. There's usually a settings.py file in your django project, it includes things like your secret keys and the file is fully expected to be altered between the local deploying machine. It is also altered for the purposes of different tests.

    There are global-style variables (such as TIME_ZONE) in the file which django expects, but I chose to add the additional dependency which I wanted to inject as a variable in this file.

    so in a real settings.py

    INTERPRETER = CustomDataInterpreter()
    

    and in views.py

    from settings import INTERPRETER
    
    def run(request):
        data = INTERPRETER.interpret(request)
        return JsonResponse(data, safe=False)
    

    I then used a settings.test.py file for testing but alternativly django has options to override settings for individual test cases see: https://docs.djangoproject.com/en/stable/topics/testing/tools/#overriding-settings