[Django]-Dealing with Class Dependencies in Python

4đź‘Ť

âś…

If the use of the Contacts package in House is limited to a single method then you put the import inside the method and catch the exception:

def foo(self):
    try:
        from Contacts.Models import Contact
    except ImportError:
        return
    ... use Contact here

Alternatively you can put the import at the top of the module but set it to None in the case where it isn’t available:

try:
    from Contacts.Models import Contact
except ImportError:
    Contact = None


...
if Contact is not None:
    ... use Contact ...

If you want to go a more pure OOP route, then you could use Zope3 adapters, but that means you’ve swapped dependency on one package for dependency on a group of others. It is likely to be overkill for the problem you’ve described, but if you want to investigate this solution see this blog post.

I think the real issue you will hit if you try this is that you’ll have to define an interface such as IContactProvider that you can fetch for your House class. That interface has to live somewhere and if that somewhere is the Contacts package you still end up requiring that package to be installed. If your need is for some sort of generic IContactProvider and several specific implementations then this could be a good way of handling that problem.

👤Duncan

1đź‘Ť

Django as signals and ProxyModels (and Python has monkeypatching when there’s no better solution). What I usually do to keep apps decoupled (when it makes sense of course) is to have a “main” django app that I use as a project-specific integration layer. In this case – and assuming House has no “hardwired” dependency on Contact (ie ForeignKey) – I’d define a ProxyModel for House where I’d add the get_contact method.

1đź‘Ť

In Django you can dynamically get model by name at run-time, which is good option to avoid circular imports. The function is django.db.models.get_model() with following signature:

def get_model(self, app_label, model_name, seed_cache=True, only_installed=True)

So your code in House model should look something like

from django.db.models import get_model
Contact = get_model('contacts', 'Contact')
👤vartec

Leave a comment